Index: net/base/io_buffer.h |
diff --git a/net/base/io_buffer.h b/net/base/io_buffer.h |
index 3a04b6a969cfe3f5ee6da2aad1f15fff0514c4e1..1c2f236ccf9fe9630194d80d084ed4d81471abbc 100644 |
--- a/net/base/io_buffer.h |
+++ b/net/base/io_buffer.h |
@@ -126,6 +126,21 @@ class NET_EXPORT StringIOBuffer : public IOBuffer { |
// This version wraps an existing IOBuffer and provides convenient functions |
// to progressively read all the data. |
+// |
+// DrainableIOBuffer is useful when you have an IOBuffer that contains data |
+// to be written progressively, and Write() function takes an IOBuffer rather |
+// than const char*. DrainableIOBuffer can be used as follows: |
+// |
+// // payload is the IOBuffer containing the data to be written. |
+// buf = new DrainableIOBuffer(payload, payload_size); |
+// |
+// while (buf->BytesRemaining() > 0) { |
+// // Write() takes an IOBuffer. If it takes const char*, we could |
+// // simply use the regular IOBuffer like payload->data() + offset. |
+// int bytes_written = Write(buf, buf->BytesRemaining()); |
+// buf->DidConsume(bytes_written); |
+// } |
+// |
class NET_EXPORT DrainableIOBuffer : public IOBuffer { |
public: |
DrainableIOBuffer(IOBuffer* base, int size); |
@@ -154,7 +169,123 @@ class NET_EXPORT DrainableIOBuffer : public IOBuffer { |
int used_; |
}; |
+// Similar to DrainableIOBuffer(), but this version comes with its own |
+// storage, so you don't need to create a separate IOBuffer. DidAppend(), |
rvargas (doing something else)
2012/02/03 23:13:34
I would prefer not having references to bad patter
satorux1
2012/02/03 23:46:11
Good point. Reworked and simplified the comment pe
|
+// capacity(), and Clear() are also provided, so that the SeekableIOBuffer is |
+// reusable. |
+// |
+// SeekableIOBuffer is useful when you want to avoid repeated allocations of |
+// DrainableIOBuffer. Consider this case: |
+// |
+// scoped_refptr<IOBuffer> buf = new IOBufferWithSize(1024); |
+// while (!some_reader->IsEOF()) { |
+// int bytes_read = some_reader->Read(buf, buf->size()); |
+// scoped_refptr<DrainableIOBuffer> drainable(buf, num_bytes); // HERE |
+// while (!drainable->BytesRemaining()) { |
+// int bytes_written = Write(drainable, drainable->BytesRemaining()); |
+// drainable->DidConsume(bytes_written); |
+// } |
+// } |
+// |
+// As shown, DrainableIOBuffer is repeatedly allocated. With |
+// SeekableIOBuffer, the extra allocations can be eliminated: |
+// |
+// scoped_refptr<SeekableIOBuffer> seekable = new SeekableIOBuffer(1024); |
+// while (!some_reader->IsEOF()) { |
+// seekable->Clear(); // Clear before reuse. |
+// int bytes_read = some_reader->Read(seekable, seekable->capacity()); |
+// seekable->DidAppend(bytes_read); |
+// while (!seekable->BytesRemaining()) { |
+// int bytes_written = Write(seekable, seekable->BytesRemaining()); |
+// seekable->DidConsume(bytes_written); |
+// } |
+// } |
+// |
+// General example: |
+// |
+// scoped_refptr<SeekableIOBuffer> buf = new SeekableIOBuffer(1024); |
+// // capacity() == 1024. size() == BytesRemaining == BytesConsumed() == 0. |
+// // data() points to the beginning of the buffer. |
+// |
+// // Read() takes an IOBuffer. |
+// int bytes_read = some_reader->Read(buf, buf->capacity()); |
+// buf->DidAppend(bytes_read); |
+// // size() == BytesRemaining() == bytes_read. data() is unaffected. |
+// |
+// while (buf->BytesRemaining() > 0) { |
+// // Write() takes an IOBuffer. If it takes const char*, we could |
+/// // simply use the regular IOBuffer like buf->data() + offset. |
+// int bytes_written = Write(buf, buf->BytesRemaining()); |
+// buf->DidConsume(bytes_written); |
+// } |
+// // BytesRemaining() == 0. BytesConsumed() == size(). |
+// // data() points to the end of the comsumed bytes (exclusive). |
+// |
+// // If you want to reuse the buffer, be sure to clear the buffer. |
+// buf->Clear(); |
+// // size() == BytesRemaining() == BytesConsumed() == 0. |
+// // data() points to the beginning of the buffer. |
+// |
+class NET_EXPORT SeekableIOBuffer : public IOBuffer { |
+ public: |
+ explicit SeekableIOBuffer(int capacity); |
+ |
+ // DidConsume() changes the |data_| pointer so that |data_| always points |
+ // to the first unconsumed byte. |
+ void DidConsume(int bytes); |
+ |
+ // Returns the number of unconsumed bytes. |
+ // GUARANTEES: 0 <= BytesRemaining() <= size(). |
rvargas (doing something else)
2012/02/03 23:13:34
nit: we have always used comments that are in regu
satorux1
2012/02/03 23:46:11
Removed.
|
+ int BytesRemaining() const; |
+ |
+ // Seeks to an arbitrary point in the buffer. The notion of bytes consumed |
+ // and remaining are updated appropriately. |
+ // REQUIRES: 0 <= bytes <= size(). |
+ void SetOffset(int bytes); |
+ |
+ // Marks that |bytes| have been appended. |bytes| is added to |size_|, but |
rvargas (doing something else)
2012/02/03 23:13:34
nit: "marks" is not that clear. Go either with "ca
satorux1
2012/02/03 23:46:11
Done.
|
+ // data() is unaffected. |
+ // REQUIRES: 0 <= |bytes| + size() <= capacity(). |
+ void DidAppend(int bytes); |
+ |
+ // Changes the logical size to 0, and the offset to 0. |
+ void Clear(); |
+ |
+ // Returns the logical size of the buffer (i.e the number of bytes of data |
+ // in the buffer). |
+ // GUARANTEES: 0 <= size() <= capacity(). |
+ int size() const { return size_; } |
+ |
+ // Returns the capacity of the buffer. The capacity is the size used when |
+ // the object is created. |
+ int capacity() const { return capacity_; }; |
+ |
+ private: |
+ virtual ~SeekableIOBuffer(); |
+ |
+ char* real_data_; |
rvargas (doing something else)
2012/02/03 23:13:34
buffer_start_ ? data_start_ ?
satorux1
2012/02/03 23:46:11
it used to be begin_, but changed to real_data_ pe
|
+ int capacity_; |
+ int size_; |
+ int used_; |
+}; |
+ |
// This version provides a resizable buffer and a changeable offset. |
+// |
+// GrowableIOBuffer is useful when you read data progressively without |
+// knowing the total size in advance. GrowableIOBuffer can be used as |
+// follows: |
+// |
+// buf = new GrowableIOBuffer; |
+// buf->SetCapacity(1024); // Initial capacity. |
+// |
+// while (!some_stream->IsEOF()) { |
+// // Double the capacity if the remaining capacity is empty. |
+// if (buf->RemainingCapacity() == 0) |
+// buf->SetCapacity(buf->capacity() * 2); |
+// int bytes_read = some_stream->Read(buf, buf->RemainingCapacity()); |
+// some_stream->set_offset(buf->offset() + bytes_read); |
rvargas (doing something else)
2012/02/03 23:13:34
This should be buf->set_offset(
satorux1
2012/02/03 23:46:11
Good catch. Done.
|
+// } |
+// |
class NET_EXPORT GrowableIOBuffer : public IOBuffer { |
public: |
GrowableIOBuffer(); |