Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve AppendableWriter performance #1706

Merged
merged 3 commits into from
Jul 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions gson/src/main/java/com/google/gson/internal/Streams.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,31 @@ private static final class AppendableWriter extends Writer {
appendable.append(currentWrite, offset, offset + length);
}

@Override public void flush() {}
@Override public void close() {}

// Override these methods for better performance
// They would otherwise unnecessarily create Strings or char arrays

@Override public void write(int i) throws IOException {
appendable.append((char) i);
}

@Override public void flush() {}
@Override public void close() {}
@Override public void write(String str, int off, int len) throws IOException {
// Appendable.append turns null -> "null", which is not desired here
$Gson$Preconditions.checkNotNull(str);
appendable.append(str, off, off + len);
}

@Override public Writer append(CharSequence csq) throws IOException {
appendable.append(csq);
return this;
}

@Override public Writer append(CharSequence csq, int start, int end) throws IOException {
appendable.append(csq, start, end);
return this;
}

/**
* A mutable char sequence pointing at a single char[].
Expand Down
68 changes: 68 additions & 0 deletions gson/src/test/java/com/google/gson/internal/StreamsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.google.gson.internal;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.io.Writer;
import org.junit.Test;

public class StreamsTest {
@Test
public void testWriterForAppendable() throws IOException {
StringBuilder stringBuilder = new StringBuilder();
Writer writer = Streams.writerForAppendable(stringBuilder);

writer.append('a');
writer.append('\u1234');
writer.append("test");
writer.append(null); // test custom null handling mandated by `append`
writer.append("abcdef", 2, 4);
writer.append(null, 1, 3); // test custom null handling mandated by `append`
writer.append(',');

writer.write('a');
writer.write('\u1234');
// Should only consider the 16 low-order bits
writer.write(0x4321_1234);
writer.append(',');

writer.write("chars".toCharArray());
try {
writer.write((char[]) null);
fail();
} catch (NullPointerException e) {
}

writer.write("chars".toCharArray(), 1, 2);
try {
writer.write((char[]) null, 1, 2);
fail();
} catch (NullPointerException e) {
}
writer.append(',');

writer.write("string");
try {
writer.write((String) null);
fail();
} catch (NullPointerException e) {
}

writer.write("string", 1, 2);
try {
writer.write((String) null, 1, 2);
fail();
} catch (NullPointerException e) {
}

String actualOutput = stringBuilder.toString();
assertEquals("a\u1234testnullcdul,a\u1234\u1234,charsha,stringtr", actualOutput);

writer.flush();
writer.close();

// flush() and close() calls should have had no effect
assertEquals(actualOutput, stringBuilder.toString());
}
}