Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(291)

Unified Diff: net/cronet/android/java/src/org/chromium/net/ChunkedWritableByteChannel.java

Issue 183333002: Cronet Java wrappers to fallback to HttpUrlConnection if Cronet is not available. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address formatting comments. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/cronet/android/java/src/org/chromium/net/ChunkedWritableByteChannel.java
diff --git a/net/cronet/android/java/src/org/chromium/net/ChunkedWritableByteChannel.java b/net/cronet/android/java/src/org/chromium/net/ChunkedWritableByteChannel.java
new file mode 100644
index 0000000000000000000000000000000000000000..638f2cb5d2da87f8f5c898536dad047e79b0ddd7
--- /dev/null
+++ b/net/cronet/android/java/src/org/chromium/net/ChunkedWritableByteChannel.java
@@ -0,0 +1,125 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.net;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.WritableByteChannel;
+import java.util.ArrayList;
+
+/**
+ * A writable byte channel that is optimized for chunked writing. Each call to
+ * {@link #write} results in a ByteBuffer being created and remembered. Then all
+ * of those byte buffers are combined on demand. This approach allows to avoid
+ * the cost of reallocating a byte buffer.
+ */
+public class ChunkedWritableByteChannel implements WritableByteChannel {
+
+ private final ArrayList<ByteBuffer> mBuffers = new ArrayList<ByteBuffer>();
+
+ private ByteBuffer mInitialBuffer;
+
+ private ByteBuffer mBuffer;
+
+ private int mSize;
+
+ private boolean mClosed;
+
+ public void setCapacity(int capacity) {
+ if (!mBuffers.isEmpty() || mInitialBuffer != null) {
+ throw new IllegalStateException();
+ }
+
+ mInitialBuffer = ByteBuffer.allocateDirect(capacity);
+ }
+
+ @Override
+ public int write(ByteBuffer buffer) throws IOException {
+ if (mClosed) {
+ throw new ClosedChannelException();
+ }
+
+ int size = buffer.remaining();
+ mSize += size;
+
+ if (mInitialBuffer != null) {
+ if (size <= mInitialBuffer.remaining()) {
+ mInitialBuffer.put(buffer);
+ return size;
+ }
+
+ // The supplied initial size was incorrect. Keep the accumulated
+ // data
+ // and switch to the usual "sequence of buffers" mode.
+ mInitialBuffer.flip();
+ mBuffers.add(mInitialBuffer);
+ mInitialBuffer = null;
+ }
+
+ // We can't hold a reference to this buffer, because it may wrap native
+ // memory
+ // and is not guaranteed to be immutable.
+ ByteBuffer tmpBuf = ByteBuffer.allocateDirect(size);
+ tmpBuf.put(buffer).rewind();
+ mBuffers.add(tmpBuf);
+ return size;
+ }
+
+ /**
+ * Returns the entire content accumulated by the channel as a ByteBuffer.
+ */
+ public ByteBuffer getByteBuffer() {
+ if (mInitialBuffer != null) {
+ mInitialBuffer.flip();
+ mBuffer = mInitialBuffer;
+ mInitialBuffer = null;
+ } else if (mBuffer != null && mSize == mBuffer.capacity()) {
+ // Cache hit
+ } else if (mBuffer == null && mBuffers.size() == 1) {
+ mBuffer = mBuffers.get(0);
+ } else {
+ mBuffer = ByteBuffer.allocateDirect(mSize);
+ int count = mBuffers.size();
+ for (int i = 0; i < count; i++) {
+ mBuffer.put(mBuffers.get(i));
+ }
+ mBuffer.rewind();
+ }
+ return mBuffer;
+ }
+
+ /**
+ * Returns the entire content accumulated by the channel as a byte array.
+ */
+ public byte[] getBytes() {
+ byte[] bytes = new byte[mSize];
+ if (mInitialBuffer != null) {
+ mInitialBuffer.flip();
+ mInitialBuffer.get(bytes);
+ } else {
+ int bufferCount = mBuffers.size();
+ int offset = 0;
+ for (int i = 0; i < bufferCount; i++) {
+ ByteBuffer buffer = mBuffers.get(i);
+ int bufferSize = buffer.remaining();
+ buffer.get(bytes, offset, bufferSize);
+ buffer.rewind();
+ offset += bufferSize;
+ }
+ }
+ return bytes;
+ }
+
+ @Override
+ public void close() {
+ mClosed = true;
+ }
+
+ @Override
+ public boolean isOpen() {
+ return !mClosed;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698