BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) { return new StandardBaseEncoding(alphabet, paddingChar); }
@Override void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOException { checkNotNull(target); checkPositionIndexes(off, off + len, bytes.length); for (int i = 0; i < len; i += alphabet.bytesPerChunk) { encodeChunkTo(target, bytes, off + i, Math.min(alphabet.bytesPerChunk, len - i)); } }
@Override public BaseEncoding withPadChar(char padChar) { if (8 % alphabet.bitsPerChar == 0 || (paddingChar != null && paddingChar.charValue() == padChar)) { return this; } else { return newInstance(alphabet, padChar); } }
int readChars = 0; boolean hitPadding = false; final CharMatcher paddingMatcher = padding();
@Override int decodeTo(byte[] target, CharSequence chars) throws DecodingException { checkNotNull(target); chars = padding().trimTrailingFrom(chars); if (!alphabet.isValidPaddingStartPosition(chars.length())) { throw new DecodingException("Invalid input length " + chars.length()); } int bytesWritten = 0; for (int charIdx = 0; charIdx < chars.length(); charIdx += alphabet.charsPerChunk) { long chunk = 0; int charsProcessed = 0; for (int i = 0; i < alphabet.charsPerChunk; i++) { chunk <<= alphabet.bitsPerChar; if (charIdx + i < chars.length()) { chunk |= alphabet.decode(chars.charAt(charIdx + charsProcessed++)); } } final int minOffset = alphabet.bytesPerChunk * 8 - charsProcessed * alphabet.bitsPerChar; for (int offset = (alphabet.bytesPerChunk - 1) * 8; offset >= minOffset; offset -= 8) { target[bytesWritten++] = (byte) ((chunk >>> offset) & 0xFF); } } return bytesWritten; }
@Override public boolean canDecode(CharSequence chars) { chars = padding().trimTrailingFrom(chars); if (!alphabet.isValidPaddingStartPosition(chars.length())) { return false; } for (int i = 0; i < chars.length(); i++) { if (!alphabet.canDecode(chars.charAt(i))) { return false; } } return true; }
@Override public BaseEncoding withSeparator(String separator, int afterEveryChars) { checkArgument( padding().or(alphabet).matchesNoneOf(separator), "Separator (%s) cannot contain alphabet or padding characters", separator); return new SeparatedBaseEncoding(this, separator, afterEveryChars); }
@Override public BaseEncoding upperCase() { BaseEncoding result = upperCase; if (result == null) { Alphabet upper = alphabet.upperCase(); result = upperCase = (upper == alphabet) ? this : newInstance(upper, paddingChar); } return result; }
@Override public BaseEncoding lowerCase() { BaseEncoding result = lowerCase; if (result == null) { Alphabet lower = alphabet.lowerCase(); result = lowerCase = (lower == alphabet) ? this : newInstance(lower, paddingChar); } return result; }
@Override public BaseEncoding omitPadding() { return (paddingChar == null) ? this : newInstance(alphabet, null); }