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