• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.crypto.tink.subtle;
18 
19 import com.google.errorprone.annotations.CanIgnoreReturnValue;
20 import java.io.UnsupportedEncodingException;
21 import java.nio.charset.Charset;
22 
23 /**
24  * Utilities for encoding and decoding the Base64 representation of binary data.
25  *
26  * <p>See RFCs <a href="http://www.ietf.org/rfc/rfc2045.txt">2045</a> and <a
27  * href="http://www.ietf.org/rfc/rfc3548.txt">3548</a>.
28  *
29  * <p>This is a copy of android.util.Base64, with minor modifications to to fix style and ErrorProne
30  * errors.
31  *
32  * @since 1.0.0
33  */
34 public final class Base64 {
35   private static final Charset UTF_8 = Charset.forName("UTF-8");
36 
37   /** Default values for encoder/decoder flags. */
38   public static final int DEFAULT = 0;
39 
40   /** Encoder flag bit to omit the padding '=' characters at the end of the output (if any). */
41   public static final int NO_PADDING = 1;
42 
43   /** Encoder flag bit to omit all line terminators (i.e., the output will be on one long line). */
44   public static final int NO_WRAP = 2;
45 
46   /**
47    * Encoder flag bit to indicate lines should be terminated with a CRLF pair instead of just an LF.
48    * Has no effect if {@code NO_WRAP} is specified as well.
49    */
50   public static final int CRLF = 4;
51 
52   /**
53    * Encoder/decoder flag bit to indicate using the "URL and filename safe" variant of Base64 (see
54    * RFC 3548 section 4) where {@code -} and {@code _} are used in place of {@code +} and {@code /}.
55    */
56   public static final int URL_SAFE = 8;
57 
58   /**
59    * Flag to pass to {@link Base64OutputStream} to indicate that it should not close the output
60    * stream it is wrapping when it itself is closed.
61    */
62   public static final int NO_CLOSE = 16;
63 
64   //  --------------------------------------------------------
65   //  shared code
66   //  --------------------------------------------------------
67 
68   /* package */ abstract static class Coder {
69     public byte[] output;
70     public int op;
71 
72     /**
73      * Encode/decode another block of input data. this.output is provided by the caller, and must be
74      * big enough to hold all the coded data. On exit, this.opwill be set to the length of the coded
75      * data.
76      *
77      * @param finish true if this is the final call to process for this object. Will finalize the
78      *     coder state and include any final bytes in the output.
79      * @return true if the input so far is good; false if some error has been detected in the input
80      *     stream..
81      */
process(byte[] input, int offset, int len, boolean finish)82     public abstract boolean process(byte[] input, int offset, int len, boolean finish);
83 
84     /**
85      * @return the maximum number of bytes a call to process() could produce for the given number of
86      *     input bytes. This may be an overestimate.
87      */
maxOutputSize(int len)88     public abstract int maxOutputSize(int len);
89   }
90 
91   //  --------------------------------------------------------
92   //  decoding
93   //  --------------------------------------------------------
94 
95   /** Decodes a base64 string to a byte array. */
decode(String input)96   public static byte[] decode(String input) {
97     return decode(input, DEFAULT | NO_WRAP);
98   }
99 
100   /**
101    * Decode the Base64-encoded data in input and return the data in a new byte array.
102    *
103    * <p>The padding '=' characters at the end are considered optional, but if any are present, there
104    * must be the correct number of them.
105    *
106    * @param str the input String to decode, which is converted to bytes using the default charset
107    * @param flags controls certain features of the decoded output. Pass {@code DEFAULT} to decode
108    *     standard Base64.
109    * @throws IllegalArgumentException if the input contains incorrect padding
110    */
decode(String str, int flags)111   public static byte[] decode(String str, int flags) {
112     return decode(str.getBytes(UTF_8), flags);
113   }
114 
115   /**
116    * Decode the Base64-encoded data in input and return the data in a new byte array.
117    *
118    * <p>The padding '=' characters at the end are considered optional, but if any are present, there
119    * must be the correct number of them.
120    *
121    * @param input the input array to decode
122    * @param flags controls certain features of the decoded output. Pass {@code DEFAULT} to decode
123    *     standard Base64.
124    * @throws IllegalArgumentException if the input contains incorrect padding
125    */
decode(byte[] input, int flags)126   public static byte[] decode(byte[] input, int flags) {
127     return decode(input, 0, input.length, flags);
128   }
129 
130   /**
131    * Decode the Base64-encoded data in input and return the data in a new byte array.
132    *
133    * <p>The padding '=' characters at the end are considered optional, but if any are present, there
134    * must be the correct number of them.
135    *
136    * @param input the data to decode
137    * @param offset the position within the input array at which to start
138    * @param len the number of bytes of input to decode
139    * @param flags controls certain features of the decoded output. Pass {@code DEFAULT} to decode
140    *     standard Base64.
141    * @throws IllegalArgumentException if the input contains incorrect padding
142    */
decode(byte[] input, int offset, int len, int flags)143   public static byte[] decode(byte[] input, int offset, int len, int flags) {
144     // Allocate space for the most data the input could represent.
145     // (It could contain less if it contains whitespace, etc.)
146     Decoder decoder = new Decoder(flags, new byte[len * 3 / 4]);
147 
148     if (!decoder.process(input, offset, len, true)) {
149       throw new IllegalArgumentException("bad base-64");
150     }
151 
152     // Maybe we got lucky and allocated exactly enough output space.
153     if (decoder.op == decoder.output.length) {
154       return decoder.output;
155     }
156 
157     // Need to shorten the array, so allocate a new one of the
158     // right size and copy.
159     byte[] temp = new byte[decoder.op];
160     System.arraycopy(decoder.output, 0, temp, 0, decoder.op);
161     return temp;
162   }
163 
164   /** Decodes a url-safe base64 string to a byte array. */
urlSafeDecode(String input)165   public static byte[] urlSafeDecode(String input) {
166     return decode(input, DEFAULT | NO_PADDING | NO_WRAP | URL_SAFE);
167   }
168 
169   /* package */ static class Decoder extends Coder {
170     /** Lookup table for turning bytes into their position in the Base64 alphabet. */
171     private static final int[] DECODE = {
172       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
173       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
174       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
175       52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
176       -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
177       15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
178       -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
179       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
180       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
181       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
182       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
183       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
184       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
185       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
186       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
187       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
188     };
189 
190     /**
191      * Decode lookup table for the "web safe" variant (RFC 3548 sec. 4) where - and _ replace + and
192      * /.
193      */
194     private static final int[] DECODE_WEBSAFE = {
195       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
196       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
197       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1,
198       52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
199       -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
200       15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
201       -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
202       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
203       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
204       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
205       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
206       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
207       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
208       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
209       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
210       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
211     };
212 
213     /** Non-data values in the DECODE arrays. */
214     private static final int SKIP = -1;
215 
216     private static final int EQUALS = -2;
217 
218     /**
219      * States 0-3 are reading through the next input tuple. State 4 is having read one '=' and
220      * expecting exactly one more. State 5 is expecting no more data or padding characters in the
221      * input. State 6 is the error state; an error has been detected in the input and no future
222      * input can "fix" it.
223      */
224     private int state; // state number (0 to 6)
225 
226     private int value;
227 
228     private final int[] alphabet;
229 
Decoder(int flags, byte[] output)230     public Decoder(int flags, byte[] output) {
231       this.output = output;
232 
233       alphabet = ((flags & URL_SAFE) == 0) ? DECODE : DECODE_WEBSAFE;
234       state = 0;
235       value = 0;
236     }
237 
238     /** @return an overestimate for the number of bytes {@code len} bytes could decode to. */
239     @Override
maxOutputSize(int len)240     public int maxOutputSize(int len) {
241       return len * 3 / 4 + 10;
242     }
243 
244     /**
245      * Decode another block of input data.
246      *
247      * @return true if the state machine is still healthy. false if bad base-64 data has been
248      *     detected in the input stream.
249      */
250     @Override
process(byte[] input, int offset, int len, boolean finish)251     public boolean process(byte[] input, int offset, int len, boolean finish) {
252       if (this.state == 6) {
253         return false;
254       }
255 
256       int p = offset;
257       len += offset;
258 
259       // Using local variables makes the decoder about 12%
260       // faster than if we manipulate the member variables in
261       // the loop.  (Even alphabet makes a measurable
262       // difference, which is somewhat surprising to me since
263       // the member variable is final.)
264       int state = this.state;
265       int value = this.value;
266       int op = 0;
267       final byte[] output = this.output;
268       final int[] alphabet = this.alphabet;
269 
270       while (p < len) {
271         if (state == 0) {
272           while (p + 4 <= len
273               && (value =
274                       ((alphabet[input[p] & 0xff] << 18)
275                           | (alphabet[input[p + 1] & 0xff] << 12)
276                           | (alphabet[input[p + 2] & 0xff] << 6)
277                           | (alphabet[input[p + 3] & 0xff])))
278                   >= 0) {
279             output[op + 2] = (byte) value;
280             output[op + 1] = (byte) (value >> 8);
281             output[op] = (byte) (value >> 16);
282             op += 3;
283             p += 4;
284           }
285           if (p >= len) {
286             break;
287           }
288         }
289 
290         // The fast path isn't available -- either we've read a
291         // partial tuple, or the next four input bytes aren't all
292         // data, or whatever.  Fall back to the slower state
293         // machine implementation.
294 
295         int d = alphabet[input[p++] & 0xff];
296 
297         switch (state) {
298           case 0:
299             if (d >= 0) {
300               value = d;
301               ++state;
302             } else if (d != SKIP) {
303               this.state = 6;
304               return false;
305             }
306             break;
307 
308           case 1:
309             if (d >= 0) {
310               value = (value << 6) | d;
311               ++state;
312             } else if (d != SKIP) {
313               this.state = 6;
314               return false;
315             }
316             break;
317 
318           case 2:
319             if (d >= 0) {
320               value = (value << 6) | d;
321               ++state;
322             } else if (d == EQUALS) {
323               // Emit the last (partial) output tuple;
324               // expect exactly one more padding character.
325               output[op++] = (byte) (value >> 4);
326               state = 4;
327             } else if (d != SKIP) {
328               this.state = 6;
329               return false;
330             }
331             break;
332 
333           case 3:
334             if (d >= 0) {
335               // Emit the output triple and return to state 0.
336               value = (value << 6) | d;
337               output[op + 2] = (byte) value;
338               output[op + 1] = (byte) (value >> 8);
339               output[op] = (byte) (value >> 16);
340               op += 3;
341               state = 0;
342             } else if (d == EQUALS) {
343               // Emit the last (partial) output tuple;
344               // expect no further data or padding characters.
345               output[op + 1] = (byte) (value >> 2);
346               output[op] = (byte) (value >> 10);
347               op += 2;
348               state = 5;
349             } else if (d != SKIP) {
350               this.state = 6;
351               return false;
352             }
353             break;
354 
355           case 4:
356             if (d == EQUALS) {
357               ++state;
358             } else if (d != SKIP) {
359               this.state = 6;
360               return false;
361             }
362             break;
363 
364           case 5:
365             if (d != SKIP) {
366               this.state = 6;
367               return false;
368             }
369             break;
370           default:
371             break;
372         }
373       }
374 
375       if (!finish) {
376         // We're out of input, but a future call could provide
377         // more.
378         this.state = state;
379         this.value = value;
380         this.op = op;
381         return true;
382       }
383 
384       // Done reading input.  Now figure out where we are left in
385       // the state machine and finish up.
386 
387       switch (state) {
388         case 0:
389           // Output length is a multiple of three.  Fine.
390           break;
391         case 1:
392           // Read one extra input byte, which isn't enough to
393           // make another output byte.  Illegal.
394           this.state = 6;
395           return false;
396         case 2:
397           // Read two extra input bytes, enough to emit 1 more
398           // output byte.  Fine.
399           output[op++] = (byte) (value >> 4);
400           break;
401         case 3:
402           // Read three extra input bytes, enough to emit 2 more
403           // output bytes.  Fine.
404           output[op++] = (byte) (value >> 10);
405           output[op++] = (byte) (value >> 2);
406           break;
407         case 4:
408           // Read one padding '=' when we expected 2.  Illegal.
409           this.state = 6;
410           return false;
411         case 5:
412           // Read all the padding '='s we expected and no more.
413           // Fine.
414           break;
415         default:
416           break;
417       }
418 
419       this.state = state;
420       this.op = op;
421       return true;
422     }
423   }
424 
425   //  --------------------------------------------------------
426   //  encoding
427   //  --------------------------------------------------------
428 
429   /** Base64 encodes a byte array to a string. */
encode(final byte[] input)430   public static String encode(final byte[] input) {
431     return encodeToString(input, DEFAULT | NO_WRAP);
432   }
433 
434   /**
435    * Base64-encode the given data and return a newly allocated byte[] with the result.
436    *
437    * @param input the data to encode
438    * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} results
439    *     in output that adheres to RFC 2045.
440    */
encode(byte[] input, int flags)441   public static byte[] encode(byte[] input, int flags) {
442     return encode(input, 0, input.length, flags);
443   }
444 
445   /**
446    * Base64-encode the given data and return a newly allocated byte[] with the result.
447    *
448    * @param input the data to encode
449    * @param offset the position within the input array at which to start
450    * @param len the number of bytes of input to encode
451    * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} results
452    *     in output that adheres to RFC 2045.
453    */
encode(byte[] input, int offset, int len, int flags)454   public static byte[] encode(byte[] input, int offset, int len, int flags) {
455     Encoder encoder = new Encoder(flags, null);
456 
457     // Compute the exact length of the array we will produce.
458     int outputLen = len / 3 * 4;
459 
460     // Account for the tail of the data and the padding bytes, if any.
461     if (encoder.doPadding) {
462       if (len % 3 > 0) {
463         outputLen += 4;
464       }
465     } else {
466       switch (len % 3) {
467         case 0:
468           break;
469         case 1:
470           outputLen += 2;
471           break;
472         case 2:
473           outputLen += 3;
474           break;
475         default:
476           break;
477       }
478     }
479 
480     // Account for the newlines, if any.
481     if (encoder.doNewline && len > 0) {
482       outputLen += (((len - 1) / (3 * Encoder.LINE_GROUPS)) + 1) * (encoder.doCr ? 2 : 1);
483     }
484 
485     encoder.output = new byte[outputLen];
486     encoder.process(input, offset, len, true);
487 
488     assert encoder.op == outputLen;
489 
490     return encoder.output;
491   }
492 
493   /** Url-safe base64 encodes a byte array to a string. */
urlSafeEncode(final byte[] input)494   public static String urlSafeEncode(final byte[] input) {
495     return encodeToString(input, DEFAULT | NO_PADDING | NO_WRAP | URL_SAFE);
496   }
497 
498   /**
499    * Base64-encode the given data and return a newly allocated String with the result.
500    *
501    * @param input the data to encode
502    * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} results
503    *     in output that adheres to RFC 2045.
504    */
encodeToString(byte[] input, int flags)505   public static String encodeToString(byte[] input, int flags) {
506     try {
507       return new String(encode(input, flags), "US-ASCII");
508     } catch (UnsupportedEncodingException e) {
509       // US-ASCII is guaranteed to be available.
510       throw new AssertionError(e);
511     }
512   }
513 
514   /**
515    * Base64-encode the given data and return a newly allocated String with the result.
516    *
517    * @param input the data to encode
518    * @param offset the position within the input array at which to start
519    * @param len the number of bytes of input to encode
520    * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} results
521    *     in output that adheres to RFC 2045.
522    */
encodeToString(byte[] input, int offset, int len, int flags)523   public static String encodeToString(byte[] input, int offset, int len, int flags) {
524     try {
525       return new String(encode(input, offset, len, flags), "US-ASCII");
526     } catch (UnsupportedEncodingException e) {
527       // US-ASCII is guaranteed to be available.
528       throw new AssertionError(e);
529     }
530   }
531 
532   /* package */ static class Encoder extends Coder {
533     /**
534      * Emit a new line every this many output tuples. Corresponds to a 76-character line length (the
535      * maximum allowable according to <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>).
536      */
537     public static final int LINE_GROUPS = 19;
538 
539     /** Lookup table for turning Base64 alphabet positions (6 bits) into output bytes. */
540     private static final byte[] ENCODE = {
541       'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
542       'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
543       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
544       'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
545     };
546 
547     /** Lookup table for turning Base64 alphabet positions (6 bits) into output bytes. */
548     private static final byte[] ENCODE_WEBSAFE = {
549       'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
550       'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
551       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
552       'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_',
553     };
554 
555     private final byte[] tail;
556     /* package */ int tailLen;
557     private int count;
558 
559     public final boolean doPadding;
560     public final boolean doNewline;
561     public final boolean doCr;
562     private final byte[] alphabet;
563 
Encoder(int flags, byte[] output)564     public Encoder(int flags, byte[] output) {
565       this.output = output;
566 
567       doPadding = (flags & NO_PADDING) == 0;
568       doNewline = (flags & NO_WRAP) == 0;
569       doCr = (flags & CRLF) != 0;
570       alphabet = ((flags & URL_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE;
571 
572       tail = new byte[2];
573       tailLen = 0;
574 
575       count = doNewline ? LINE_GROUPS : -1;
576     }
577 
578     /** @return an overestimate for the number of bytes {@code len} bytes could encode to. */
579     @Override
maxOutputSize(int len)580     public int maxOutputSize(int len) {
581       return len * 8 / 5 + 10;
582     }
583 
584     /**
585      * Processes the input to encode it in base 64.
586      *
587      * <p>This function always returns true -- encoding can never fail. So if one knows that one has
588      * this class one can ignore the return value.
589      */
590     @CanIgnoreReturnValue
591     @Override
process(byte[] input, int offset, int len, boolean finish)592     public boolean process(byte[] input, int offset, int len, boolean finish) {
593       // Using local variables makes the encoder about 9% faster.
594       final byte[] alphabet = this.alphabet;
595       final byte[] output = this.output;
596       int op = 0;
597       int count = this.count;
598 
599       int p = offset;
600       len += offset;
601       int v = -1;
602 
603       // First we need to concatenate the tail of the previous call
604       // with any input bytes available now and see if we can empty
605       // the tail.
606 
607       switch (tailLen) {
608         case 0:
609           // There was no tail.
610           break;
611 
612         case 1:
613           if (p + 2 <= len) {
614             // A 1-byte tail with at least 2 bytes of
615             // input available now.
616             v = ((tail[0] & 0xff) << 16) | ((input[p++] & 0xff) << 8) | (input[p++] & 0xff);
617             tailLen = 0;
618           }
619           break;
620 
621         case 2:
622           if (p + 1 <= len) {
623             // A 2-byte tail with at least 1 byte of input.
624             v = ((tail[0] & 0xff) << 16) | ((tail[1] & 0xff) << 8) | (input[p++] & 0xff);
625             tailLen = 0;
626           }
627           break;
628         default:
629           break;
630       }
631 
632       if (v != -1) {
633         output[op++] = alphabet[(v >> 18) & 0x3f];
634         output[op++] = alphabet[(v >> 12) & 0x3f];
635         output[op++] = alphabet[(v >> 6) & 0x3f];
636         output[op++] = alphabet[v & 0x3f];
637         if (--count == 0) {
638           if (doCr) {
639             output[op++] = '\r';
640           }
641           output[op++] = '\n';
642           count = LINE_GROUPS;
643         }
644       }
645 
646       // At this point either there is no tail, or there are fewer
647       // than 3 bytes of input available.
648 
649       // The main loop, turning 3 input bytes into 4 output bytes on
650       // each iteration.
651       while (p + 3 <= len) {
652         v = ((input[p] & 0xff) << 16) | ((input[p + 1] & 0xff) << 8) | (input[p + 2] & 0xff);
653         output[op] = alphabet[(v >> 18) & 0x3f];
654         output[op + 1] = alphabet[(v >> 12) & 0x3f];
655         output[op + 2] = alphabet[(v >> 6) & 0x3f];
656         output[op + 3] = alphabet[v & 0x3f];
657         p += 3;
658         op += 4;
659         if (--count == 0) {
660           if (doCr) {
661             output[op++] = '\r';
662           }
663           output[op++] = '\n';
664           count = LINE_GROUPS;
665         }
666       }
667 
668       if (finish) {
669         // Finish up the tail of the input.  Note that we need to
670         // consume any bytes in tail before any bytes
671         // remaining in input; there should be at most two bytes
672         // total.
673 
674         if (p - tailLen == len - 1) {
675           int t = 0;
676           v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4;
677           tailLen -= t;
678           output[op++] = alphabet[(v >> 6) & 0x3f];
679           output[op++] = alphabet[v & 0x3f];
680           if (doPadding) {
681             output[op++] = '=';
682             output[op++] = '=';
683           }
684           if (doNewline) {
685             if (doCr) {
686               output[op++] = '\r';
687             }
688             output[op++] = '\n';
689           }
690         } else if (p - tailLen == len - 2) {
691           int t = 0;
692           v =
693               (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10)
694                   | (((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2);
695           tailLen -= t;
696           output[op++] = alphabet[(v >> 12) & 0x3f];
697           output[op++] = alphabet[(v >> 6) & 0x3f];
698           output[op++] = alphabet[v & 0x3f];
699           if (doPadding) {
700             output[op++] = '=';
701           }
702           if (doNewline) {
703             if (doCr) {
704               output[op++] = '\r';
705             }
706             output[op++] = '\n';
707           }
708         } else if (doNewline && op > 0 && count != LINE_GROUPS) {
709           if (doCr) {
710             output[op++] = '\r';
711           }
712           output[op++] = '\n';
713         }
714 
715         assert tailLen == 0;
716         assert p == len;
717       } else {
718         // Save the leftovers in tail to be consumed on the next
719         // call to encodeInternal.
720 
721         if (p == len - 1) {
722           tail[tailLen++] = input[p];
723         } else if (p == len - 2) {
724           tail[tailLen++] = input[p];
725           tail[tailLen++] = input[p + 1];
726         }
727       }
728 
729       this.op = op;
730       this.count = count;
731 
732       return true;
733     }
734   }
735 
Base64()736   private Base64() {} // don't instantiate
737 }
738