| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "post_buffer.h" |
| |
| #include <cstring> |
| #include <new> |
| |
| namespace gapir { |
| |
| PostBuffer::PostBuffer(uint32_t desiredCapacity, PostBufferCallback callback) : |
| mBuffer(new (std::nothrow) uint8_t[desiredCapacity]), |
| mCapacity(mBuffer ? desiredCapacity : 0), mCallback(callback), mOffset(0) { |
| } |
| |
| PostBuffer::~PostBuffer() { |
| flush(); |
| } |
| |
| bool PostBuffer::push(const void* address, uint32_t count) { |
| if (mOffset == 0 && (count > mCapacity / 2)) { |
| // Large push into an empty buffer. |
| // Write it out immediately instead of buffering to reduce time spent copying |
| // large buffers around. This also handles the case where the count is larger |
| // than the buffer capacity. |
| return mCallback(address, count); |
| } |
| |
| if (mOffset + count <= mCapacity) { |
| // Fits in the buffer. Copy. |
| memcpy(mBuffer.get() + mOffset, address, count); |
| mOffset += count; |
| return true; |
| } else { |
| // Not enough capacity to fit push data. Flush and try again. |
| return flush() && push(address, count); |
| } |
| } |
| |
| bool PostBuffer::flush() { |
| bool ok = true; |
| |
| if (mOffset > 0) { |
| ok = mCallback(mBuffer.get(), mOffset); |
| mOffset = 0; |
| } |
| return ok; |
| } |
| |
| } // namespace gapir |