(String name, char[] chars)
| 451 | private final boolean[] validPadding; |
| 452 | |
| 453 | Alphabet(String name, char[] chars) { |
| 454 | this.name = checkNotNull(name); |
| 455 | this.chars = checkNotNull(chars); |
| 456 | try { |
| 457 | this.bitsPerChar = log2(chars.length, UNNECESSARY); |
| 458 | } catch (ArithmeticException e) { |
| 459 | throw new IllegalArgumentException("Illegal alphabet length " + chars.length, e); |
| 460 | } |
| 461 | |
| 462 | /* |
| 463 | * e.g. for base64, bitsPerChar == 6, charsPerChunk == 4, and bytesPerChunk == 3. This makes |
| 464 | * for the smallest chunk size that still has charsPerChunk * bitsPerChar be a multiple of 8. |
| 465 | */ |
| 466 | |
| 467 | int gcd = Math.min(8, Integer.lowestOneBit(bitsPerChar)); |
| 468 | try { |
| 469 | this.charsPerChunk = 8 / gcd; |
| 470 | this.bytesPerChunk = bitsPerChar / gcd; |
| 471 | } catch (ArithmeticException e) { |
| 472 | throw new IllegalArgumentException("Illegal alphabet " + new String(chars), e); |
| 473 | } |
| 474 | this.mask = chars.length - 1; |
| 475 | byte[] decodabet = new byte[Ascii.MAX + 1]; |
| 476 | Arrays.fill(decodabet, (byte) -1); |
| 477 | for (int i = 0; i < chars.length; i++) { |
| 478 | char c = chars[i]; |
| 479 | checkArgument(CharMatcher.ascii().matches(c), "Non-ASCII character: %s", c); |
| 480 | checkArgument(decodabet[c] == -1, "Duplicate character: %s", c); |
| 481 | decodabet[c] = (byte) i; |
| 482 | } |
| 483 | this.decodabet = decodabet; |
| 484 | boolean[] validPadding = new boolean[charsPerChunk]; |
| 485 | for (int i = 0; i < bytesPerChunk; i++) { |
| 486 | validPadding[divide(i * 8, bitsPerChar, CEILING)] = true; |
| 487 | } |
| 488 | this.validPadding = validPadding; |
| 489 | } |
| 490 | |
| 491 | char encode(int bits) { |
| 492 | return chars[bits]; |
nothing calls this directly
no test coverage detected