Fix crash in SpeechRecognizerImpl introduced in AudioParams refactor.
[chromium-blink-merge.git] / net / tools / balsa / simple_buffer.cc
blob5e02a7b8d68df34da71dee928d9c8061e7480399
1 // Copyright 2013 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.
5 #include "net/tools/balsa/simple_buffer.h"
6 #include "base/logging.h"
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.
19 namespace net {
21 static const int kInitialSimpleBufferSize = 10;
23 SimpleBuffer::SimpleBuffer()
24 : storage_(new char[kInitialSimpleBufferSize]),
25 write_idx_(0),
26 read_idx_(0),
27 storage_size_(kInitialSimpleBufferSize) {
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];
40 SimpleBuffer::~SimpleBuffer() {
41 delete[] storage_;
45 ////////////////////////////////////////////////////////////////////////////////
47 int SimpleBuffer::ReadableBytes() const {
48 return write_idx_ - read_idx_;
51 ////////////////////////////////////////////////////////////////////////////////
53 std::string SimpleBuffer::str() const {
54 std::string s;
55 char * readable_ptr;
56 int readable_size;
57 GetReadablePtr(&readable_ptr, &readable_size);
58 s.append(readable_ptr, readable_ptr + readable_size);
59 return s;
62 ////////////////////////////////////////////////////////////////////////////////
64 int SimpleBuffer::BufferSize() const {
65 return storage_size_;
68 ////////////////////////////////////////////////////////////////////////////////
70 inline int SimpleBuffer::BytesFree() const {
71 return (storage_size_ - write_idx_);
74 ////////////////////////////////////////////////////////////////////////////////
76 bool SimpleBuffer::Empty() const {
77 return (read_idx_ == write_idx_);
80 ////////////////////////////////////////////////////////////////////////////////
82 bool SimpleBuffer::Full() const {
83 return ((write_idx_ == storage_size_) && (read_idx_ != write_idx_));
86 ////////////////////////////////////////////////////////////////////////////////
88 // returns the number of characters written.
89 // appends up-to-'size' bytes to the simplebuffer.
90 int SimpleBuffer::Write(const char* bytes, int size) {
91 bool has_room = ((storage_size_ - write_idx_) >= size);
92 if (!has_room) {
93 (void)Reserve(size);
95 memcpy(storage_ + write_idx_, bytes, size);
96 SimpleBuffer::AdvanceWritablePtr(size);
97 return size;
100 ////////////////////////////////////////////////////////////////////////////////
102 // stores a pointer into the simple buffer in *ptr,
103 // and stores the number of characters which are allowed
104 // to be written in *size.
105 inline void SimpleBuffer::GetWritablePtr(char **ptr, int* size) const {
106 *ptr = storage_ + write_idx_;
107 *size = SimpleBuffer::BytesFree();
110 ////////////////////////////////////////////////////////////////////////////////
112 // stores a pointer into the simple buffer in *ptr,
113 // and stores the number of characters which are allowed
114 // to be read in *size.
115 void SimpleBuffer::GetReadablePtr(char **ptr, int* size) const {
116 *ptr = storage_ + read_idx_;
117 *size = write_idx_ - read_idx_;
120 ////////////////////////////////////////////////////////////////////////////////
122 // returns the number of bytes read into 'bytes'
123 int SimpleBuffer::Read(char* bytes, int size) {
124 char * read_ptr = NULL;
125 int read_size = 0;
126 GetReadablePtr(&read_ptr, &read_size);
127 if (read_size > size) {
128 read_size = size;
130 memcpy(bytes, read_ptr, read_size);
131 AdvanceReadablePtr(read_size);
132 return read_size;
135 ////////////////////////////////////////////////////////////////////////////////
137 // removes all data from the simple buffer
138 void SimpleBuffer::Clear() {
139 read_idx_ = write_idx_ = 0;
142 ////////////////////////////////////////////////////////////////////////////////
144 // Attempts to reserve a contiguous block of buffer space by either reclaiming
145 // old data that is already read, and reallocate large storage as needed.
146 bool SimpleBuffer::Reserve(int size) {
147 if (size > 0 && BytesFree() < size) {
148 char * read_ptr = NULL;
149 int read_size = 0;
150 GetReadablePtr(&read_ptr, &read_size);
152 if (read_size + size <= BufferSize()) {
153 // Can reclaim space from already read bytes by shifting
154 memmove(storage_, read_ptr, read_size);
155 read_idx_ = 0;
156 write_idx_ = read_size;
157 CHECK_GE(BytesFree(), size);
158 } else {
159 // what we need is to have at least size bytes available for writing.
160 // This implies that the buffer needs to be at least size bytes +
161 // read_size bytes long. Since we want linear time extensions in the case
162 // that we're extending this thing repeatedly, we should extend to twice
163 // the current size (if that is big enough), or the size + read_size
164 // bytes, whichever is larger.
165 int new_storage_size = 2 * storage_size_;
166 if (new_storage_size < size + read_size) {
167 new_storage_size = size + read_size;
170 // have to extend the thing
171 char* new_storage = new char[new_storage_size];
173 // copy still useful info to the new buffer.
174 memcpy(new_storage, read_ptr, read_size);
175 // reset pointers.
176 read_idx_ = 0;
177 write_idx_ = read_size;
178 delete[] storage_;
179 storage_ = new_storage;
180 storage_size_ = new_storage_size;
183 return true;
186 ////////////////////////////////////////////////////////////////////////////////
188 // removes the oldest 'amount_to_consume' characters.
189 void SimpleBuffer::AdvanceReadablePtr(int amount_to_advance) {
190 read_idx_ += amount_to_advance;
191 if (read_idx_ > storage_size_) {
192 read_idx_ = storage_size_;
196 ////////////////////////////////////////////////////////////////////////////////
198 // Moves the internal pointers around such that the
199 // amount of data specified here is expected to
200 // already be resident (as if it was Written)
201 inline void SimpleBuffer::AdvanceWritablePtr(int amount_to_advance) {
202 write_idx_ += amount_to_advance;
203 if (write_idx_ > storage_size_) {
204 write_idx_ = storage_size_;
208 } // namespace net