Skip to content

Commit

Permalink
Avoid dependency on CharMatcher in BaseEncoding.
Browse files Browse the repository at this point in the history
Effects on BaseEncodingProGuard:
82416 bytes => 69250 bytes
33 classes => 16 classes
198 methods => 136 methods

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=164041197
  • Loading branch information
lowasser authored and cpovirk committed Aug 3, 2017
1 parent 106e7ee commit 4740f24
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 76 deletions.
113 changes: 75 additions & 38 deletions android/guava/src/com/google/common/io/BaseEncoding.java
Expand Up @@ -27,7 +27,6 @@
import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Ascii; import com.google.common.base.Ascii;
import com.google.common.base.CharMatcher;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
Expand Down Expand Up @@ -224,7 +223,7 @@ public final byte[] decode(CharSequence chars) {
* encoding. * encoding.
*/ final byte[] decodeChecked(CharSequence chars) */ final byte[] decodeChecked(CharSequence chars)
throws DecodingException { throws DecodingException {
chars = padding().trimTrailingFrom(chars); chars = trimTrailingPadding(chars);
byte[] tmp = new byte[maxDecodedSize(chars.length())]; byte[] tmp = new byte[maxDecodedSize(chars.length())];
int len = decodeTo(tmp, chars); int len = decodeTo(tmp, chars);
return extract(tmp, len); return extract(tmp, len);
Expand Down Expand Up @@ -263,7 +262,9 @@ public InputStream openStream() throws IOException {


abstract int decodeTo(byte[] target, CharSequence chars) throws DecodingException; abstract int decodeTo(byte[] target, CharSequence chars) throws DecodingException;


abstract CharMatcher padding(); CharSequence trimTrailingPadding(CharSequence chars) {
return checkNotNull(chars);
}


// Modified encoding generators // Modified encoding generators


Expand Down Expand Up @@ -412,7 +413,7 @@ public static BaseEncoding base16() {
return BASE16; return BASE16;
} }


private static final class Alphabet extends CharMatcher { private static final class Alphabet {
private final String name; private final String name;
// this is meant to be immutable -- don't modify it! // this is meant to be immutable -- don't modify it!
private final char[] chars; private final char[] chars;
Expand Down Expand Up @@ -450,7 +451,7 @@ private static final class Alphabet extends CharMatcher {
Arrays.fill(decodabet, (byte) -1); Arrays.fill(decodabet, (byte) -1);
for (int i = 0; i < chars.length; i++) { for (int i = 0; i < chars.length; i++) {
char c = chars[i]; char c = chars[i];
checkArgument(CharMatcher.ascii().matches(c), "Non-ASCII character: %s", c); checkArgument(c < decodabet.length, "Non-ASCII character: %s", c);
checkArgument(decodabet[c] == -1, "Duplicate character: %s", c); checkArgument(decodabet[c] == -1, "Duplicate character: %s", c);
decodabet[c] = (byte) i; decodabet[c] = (byte) i;
} }
Expand All @@ -476,12 +477,18 @@ boolean canDecode(char ch) {
} }


int decode(char ch) throws DecodingException { int decode(char ch) throws DecodingException {
if (ch > Ascii.MAX || decodabet[ch] == -1) { if (ch > Ascii.MAX) {
throw new DecodingException( throw new DecodingException("Unrecognized character: 0x" + Integer.toHexString(ch));
"Unrecognized character: " }
+ (CharMatcher.invisible().matches(ch) ? "0x" + Integer.toHexString(ch) : ch)); int result = decodabet[ch];
if (result == -1) {
if (ch <= 0x20 || ch == Ascii.MAX) {
throw new DecodingException("Unrecognized character: 0x" + Integer.toHexString(ch));
} else {
throw new DecodingException("Unrecognized character: " + ch);
}
} }
return decodabet[ch]; return result;
} }


private boolean hasLowerCase() { private boolean hasLowerCase() {
Expand Down Expand Up @@ -528,9 +535,8 @@ Alphabet lowerCase() {
} }
} }


@Override
public boolean matches(char c) { public boolean matches(char c) {
return CharMatcher.ascii().matches(c) && decodabet[c] != -1; return c < decodabet.length && decodabet[c] != -1;
} }


@Override @Override
Expand Down Expand Up @@ -572,11 +578,6 @@ static class StandardBaseEncoding extends BaseEncoding {
this.paddingChar = paddingChar; this.paddingChar = paddingChar;
} }


@Override
CharMatcher padding() {
return (paddingChar == null) ? CharMatcher.none() : CharMatcher.is(paddingChar.charValue());
}

@Override @Override
int maxEncodedSize(int bytes) { int maxEncodedSize(int bytes) {
return alphabet.charsPerChunk * divide(bytes, alphabet.bytesPerChunk, CEILING); return alphabet.charsPerChunk * divide(bytes, alphabet.bytesPerChunk, CEILING);
Expand Down Expand Up @@ -666,9 +667,26 @@ int maxDecodedSize(int chars) {
return (int) ((alphabet.bitsPerChar * (long) chars + 7L) / 8L); return (int) ((alphabet.bitsPerChar * (long) chars + 7L) / 8L);
} }


@Override
CharSequence trimTrailingPadding(CharSequence chars) {
checkNotNull(chars);
if (paddingChar == null) {
return chars;
}
char padChar = paddingChar.charValue();
int l;
for (l = chars.length() - 1; l >= 0; l--) {
if (chars.charAt(l) != padChar) {
break;
}
}
return chars.subSequence(0, l + 1);
}

@Override @Override
public boolean canDecode(CharSequence chars) { public boolean canDecode(CharSequence chars) {
chars = padding().trimTrailingFrom(chars); checkNotNull(chars);
chars = trimTrailingPadding(chars);
if (!alphabet.isValidPaddingStartPosition(chars.length())) { if (!alphabet.isValidPaddingStartPosition(chars.length())) {
return false; return false;
} }
Expand All @@ -683,7 +701,7 @@ public boolean canDecode(CharSequence chars) {
@Override @Override
int decodeTo(byte[] target, CharSequence chars) throws DecodingException { int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
checkNotNull(target); checkNotNull(target);
chars = padding().trimTrailingFrom(chars); chars = trimTrailingPadding(chars);
if (!alphabet.isValidPaddingStartPosition(chars.length())) { if (!alphabet.isValidPaddingStartPosition(chars.length())) {
throw new DecodingException("Invalid input length " + chars.length()); throw new DecodingException("Invalid input length " + chars.length());
} }
Expand All @@ -705,16 +723,15 @@ int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
return bytesWritten; return bytesWritten;
} }


@GwtIncompatible // Reader,InputStream
@Override @Override
@GwtIncompatible // Reader,InputStream
public InputStream decodingStream(final Reader reader) { public InputStream decodingStream(final Reader reader) {
checkNotNull(reader); checkNotNull(reader);
return new InputStream() { return new InputStream() {
int bitBuffer = 0; int bitBuffer = 0;
int bitBufferLength = 0; int bitBufferLength = 0;
int readChars = 0; int readChars = 0;
boolean hitPadding = false; boolean hitPadding = false;
final CharMatcher paddingMatcher = padding();


@Override @Override
public int read() throws IOException { public int read() throws IOException {
Expand All @@ -728,7 +745,7 @@ public int read() throws IOException {
} }
readChars++; readChars++;
char ch = (char) readChar; char ch = (char) readChar;
if (paddingMatcher.matches(ch)) { if (paddingChar != null && paddingChar.charValue() == ch) {
if (!hitPadding if (!hitPadding
&& (readChars == 1 || !alphabet.isValidPaddingStartPosition(readChars - 1))) { && (readChars == 1 || !alphabet.isValidPaddingStartPosition(readChars - 1))) {
throw new DecodingException("Padding cannot start at index " + readChars); throw new DecodingException("Padding cannot start at index " + readChars);
Expand Down Expand Up @@ -774,10 +791,18 @@ public BaseEncoding withPadChar(char padChar) {


@Override @Override
public BaseEncoding withSeparator(String separator, int afterEveryChars) { public BaseEncoding withSeparator(String separator, int afterEveryChars) {
checkArgument( for (int i = 0; i < separator.length(); i++) {
padding().or(alphabet).matchesNoneOf(separator), checkArgument(
"Separator (%s) cannot contain alphabet or padding characters", !alphabet.matches(separator.charAt(i)),
separator); "Separator (%s) cannot contain alphabet characters",
separator);
}
if (paddingChar != null) {
checkArgument(
separator.indexOf(paddingChar.charValue()) < 0,
"Separator (%s) cannot contain padding character",
separator);
}
return new SeparatedBaseEncoding(this, separator, afterEveryChars); return new SeparatedBaseEncoding(this, separator, afterEveryChars);
} }


Expand Down Expand Up @@ -917,7 +942,7 @@ void encodeTo(Appendable target, byte[] bytes, int off, int len) throws IOExcept
@Override @Override
int decodeTo(byte[] target, CharSequence chars) throws DecodingException { int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
checkNotNull(target); checkNotNull(target);
chars = padding().trimTrailingFrom(chars); chars = trimTrailingPadding(chars);
if (!alphabet.isValidPaddingStartPosition(chars.length())) { if (!alphabet.isValidPaddingStartPosition(chars.length())) {
throw new DecodingException("Invalid input length " + chars.length()); throw new DecodingException("Invalid input length " + chars.length());
} }
Expand All @@ -944,8 +969,8 @@ BaseEncoding newInstance(Alphabet alphabet, @Nullable Character paddingChar) {
} }
} }


@GwtIncompatible // Reader @GwtIncompatible
static Reader ignoringReader(final Reader delegate, final CharMatcher toIgnore) { static Reader ignoringReader(final Reader delegate, final String toIgnore) {
checkNotNull(delegate); checkNotNull(delegate);
checkNotNull(toIgnore); checkNotNull(toIgnore);
return new Reader() { return new Reader() {
Expand All @@ -954,7 +979,7 @@ public int read() throws IOException {
int readChar; int readChar;
do { do {
readChar = delegate.read(); readChar = delegate.read();
} while (readChar != -1 && toIgnore.matches((char) readChar)); } while (readChar != -1 && toIgnore.indexOf((char) readChar) >= 0);
return readChar; return readChar;
} }


Expand Down Expand Up @@ -1033,20 +1058,18 @@ static final class SeparatedBaseEncoding extends BaseEncoding {
private final BaseEncoding delegate; private final BaseEncoding delegate;
private final String separator; private final String separator;
private final int afterEveryChars; private final int afterEveryChars;
private final CharMatcher separatorChars;


SeparatedBaseEncoding(BaseEncoding delegate, String separator, int afterEveryChars) { SeparatedBaseEncoding(BaseEncoding delegate, String separator, int afterEveryChars) {
this.delegate = checkNotNull(delegate); this.delegate = checkNotNull(delegate);
this.separator = checkNotNull(separator); this.separator = checkNotNull(separator);
this.afterEveryChars = afterEveryChars; this.afterEveryChars = afterEveryChars;
checkArgument( checkArgument(
afterEveryChars > 0, "Cannot add a separator after every %s chars", afterEveryChars); afterEveryChars > 0, "Cannot add a separator after every %s chars", afterEveryChars);
this.separatorChars = CharMatcher.anyOf(separator).precomputed();
} }


@Override @Override
CharMatcher padding() { CharSequence trimTrailingPadding(CharSequence chars) {
return delegate.padding(); return delegate.trimTrailingPadding(chars);
} }


@Override @Override
Expand Down Expand Up @@ -1074,18 +1097,32 @@ int maxDecodedSize(int chars) {


@Override @Override
public boolean canDecode(CharSequence chars) { public boolean canDecode(CharSequence chars) {
return delegate.canDecode(separatorChars.removeFrom(chars)); StringBuilder builder = new StringBuilder();
for (int i = 0; i < chars.length(); i++) {
char c = chars.charAt(i);
if (separator.indexOf(c) < 0) {
builder.append(c);
}
}
return delegate.canDecode(builder);
} }


@Override @Override
int decodeTo(byte[] target, CharSequence chars) throws DecodingException { int decodeTo(byte[] target, CharSequence chars) throws DecodingException {
return delegate.decodeTo(target, separatorChars.removeFrom(chars)); StringBuilder stripped = new StringBuilder(chars.length());
for (int i = 0; i < chars.length(); i++) {
char c = chars.charAt(i);
if (separator.indexOf(c) < 0) {
stripped.append(c);
}
}
return delegate.decodeTo(target, stripped);
} }


@GwtIncompatible // Reader,InputStream
@Override @Override
@GwtIncompatible // Reader,InputStream
public InputStream decodingStream(final Reader reader) { public InputStream decodingStream(final Reader reader) {
return delegate.decodingStream(ignoringReader(reader, separatorChars)); return delegate.decodingStream(ignoringReader(reader, separator));
} }


@Override @Override
Expand Down

0 comments on commit 4740f24

Please sign in to comment.