• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/tools/flip_server/simple_buffer.h"
6 #include "base/logging.h"
7 
8 // Some of the following member functions are marked inlined, even though they
9 // are virtual. This may seem counter-intuitive, since virtual functions are
10 // generally not eligible for inlining. Profiling results indicate that these
11 // large amount of runtime is spent on virtual function dispatch on these
12 // simple functions. They are virtual because of the interface this class
13 // inherits from. However, it is very unlikely that anyone will sub-class
14 // SimpleBuffer and change their implementation. To get rid of this baggage,
15 // internal implementation (e.g., Write) explicitly use SimpleBuffer:: to
16 // qualify the method calls, thus disabling the virtual dispatch and enable
17 // inlining.
18 
19 namespace net {
20 
21 static const int kInitialSimpleBufferSize = 10;
22 
SimpleBuffer()23 SimpleBuffer::SimpleBuffer()
24   : storage_(new char[kInitialSimpleBufferSize]),
25     write_idx_(0),
26     read_idx_(0),
27     storage_size_(kInitialSimpleBufferSize) {
28 }
29 
SimpleBuffer(int size)30 SimpleBuffer::SimpleBuffer(int size)
31   : write_idx_(0),
32     read_idx_(0),
33     storage_size_(size) {
34   // Callers may try to allocate overly large blocks, but negative sizes are
35   // obviously wrong.
36   CHECK_GE(size, 0);
37   storage_ = new char[size];
38 }
39 
40 ////////////////////////////////////////////////////////////////////////////////
41 
ReadableBytes() const42 int SimpleBuffer::ReadableBytes() const {
43   return write_idx_ - read_idx_;
44 }
45 
46 ////////////////////////////////////////////////////////////////////////////////
47 
str() const48 std::string SimpleBuffer::str() const {
49   std::string s;
50   char * readable_ptr;
51   int readable_size;
52   GetReadablePtr(&readable_ptr, &readable_size);
53   s.append(readable_ptr, readable_ptr + readable_size);
54   return s;
55 }
56 
57 ////////////////////////////////////////////////////////////////////////////////
58 
BufferSize() const59 int SimpleBuffer::BufferSize() const {
60   return storage_size_;
61 }
62 
63 ////////////////////////////////////////////////////////////////////////////////
64 
BytesFree() const65 inline int SimpleBuffer::BytesFree() const {
66   return (storage_size_ - write_idx_);
67 }
68 
69 ////////////////////////////////////////////////////////////////////////////////
70 
Empty() const71 bool SimpleBuffer::Empty() const {
72   return (read_idx_ == write_idx_);
73 }
74 
75 ////////////////////////////////////////////////////////////////////////////////
76 
Full() const77 bool SimpleBuffer::Full() const {
78   return ((write_idx_ == storage_size_) && (read_idx_ != write_idx_));
79 }
80 
81 ////////////////////////////////////////////////////////////////////////////////
82 
83 // returns the number of characters written.
84 // appends up-to-'size' bytes to the simplebuffer.
Write(const char * bytes,int size)85 int SimpleBuffer::Write(const char* bytes, int size) {
86   bool has_room = ((storage_size_ - write_idx_) >= size);
87   if (!has_room) {
88     (void)Reserve(size);
89   }
90   memcpy(storage_ + write_idx_, bytes, size);
91   SimpleBuffer::AdvanceWritablePtr(size);
92   return size;
93 }
94 
95 ////////////////////////////////////////////////////////////////////////////////
96 
97 // stores a pointer into the simple buffer in *ptr,
98 // and stores the number of characters which are allowed
99 // to be written in *size.
GetWritablePtr(char ** ptr,int * size) const100 inline void SimpleBuffer::GetWritablePtr(char **ptr, int* size) const {
101   *ptr = storage_ + write_idx_;
102   *size = SimpleBuffer::BytesFree();
103 }
104 
105 ////////////////////////////////////////////////////////////////////////////////
106 
107 // stores a pointer into the simple buffer in *ptr,
108 // and stores the number of characters which are allowed
109 // to be read in *size.
GetReadablePtr(char ** ptr,int * size) const110 void SimpleBuffer::GetReadablePtr(char **ptr, int* size) const {
111   *ptr = storage_ + read_idx_;
112   *size = write_idx_ - read_idx_;
113 }
114 
115 ////////////////////////////////////////////////////////////////////////////////
116 
117 // returns the number of bytes read into 'bytes'
Read(char * bytes,int size)118 int SimpleBuffer::Read(char* bytes, int size) {
119   char * read_ptr = NULL;
120   int read_size = 0;
121   GetReadablePtr(&read_ptr, &read_size);
122   if (read_size > size) {
123     read_size = size;
124   }
125   memcpy(bytes, read_ptr, read_size);
126   AdvanceReadablePtr(read_size);
127   return read_size;
128 }
129 
130 ////////////////////////////////////////////////////////////////////////////////
131 
132 // removes all data from the simple buffer
Clear()133 void SimpleBuffer::Clear() {
134   read_idx_ = write_idx_ = 0;
135 }
136 
137 ////////////////////////////////////////////////////////////////////////////////
138 
139 // Attempts to reserve a contiguous block of buffer space by either reclaiming
140 // old data that is already read, and reallocate large storage as needed.
Reserve(int size)141 bool SimpleBuffer::Reserve(int size) {
142   if (size > 0 && BytesFree() < size) {
143     char * read_ptr = NULL;
144     int read_size = 0;
145     GetReadablePtr(&read_ptr, &read_size);
146 
147     if (read_size + size <= BufferSize()) {
148       // Can reclaim space from already read bytes by shifting
149       memmove(storage_, read_ptr, read_size);
150       read_idx_ = 0;
151       write_idx_ = read_size;
152       CHECK_GE(BytesFree(), size);
153     } else {
154       // what we need is to have at least size bytes available for writing.
155       // This implies that the buffer needs to be at least size bytes +
156       // read_size bytes long. Since we want linear time extensions in the case
157       // that we're extending this thing repeatedly, we should extend to twice
158       // the current size (if that is big enough), or the size + read_size
159       // bytes, whichever is larger.
160       int new_storage_size = 2 * storage_size_;
161       if (new_storage_size < size + read_size) {
162         new_storage_size = size + read_size;
163       }
164 
165       // have to extend the thing
166       char* new_storage = new char[new_storage_size];
167 
168       // copy still useful info to the new buffer.
169       memcpy(new_storage, read_ptr, read_size);
170       // reset pointers.
171       read_idx_ = 0;
172       write_idx_ = read_size;
173       delete[] storage_;
174       storage_ = new_storage;
175       storage_size_ = new_storage_size;
176     }
177   }
178   return true;
179 }
180 
181 ////////////////////////////////////////////////////////////////////////////////
182 
183 // removes the oldest 'amount_to_consume' characters.
AdvanceReadablePtr(int amount_to_advance)184 void SimpleBuffer::AdvanceReadablePtr(int amount_to_advance) {
185   read_idx_ += amount_to_advance;
186   if (read_idx_ > storage_size_) {
187     read_idx_ = storage_size_;
188   }
189 }
190 
191 ////////////////////////////////////////////////////////////////////////////////
192 
193 // Moves the internal pointers around such that the
194 // amount of data specified here is expected to
195 // already be resident (as if it was Written)
AdvanceWritablePtr(int amount_to_advance)196 inline void SimpleBuffer::AdvanceWritablePtr(int amount_to_advance) {
197   write_idx_ += amount_to_advance;
198   if (write_idx_ > storage_size_) {
199     write_idx_ = storage_size_;
200   }
201 }
202 
203 }  // namespace net
204 
205