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