diff options
Diffstat (limited to 'tools/aapt2/BigBuffer.h')
-rw-r--r-- | tools/aapt2/BigBuffer.h | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/tools/aapt2/BigBuffer.h b/tools/aapt2/BigBuffer.h new file mode 100644 index 0000000..025142b --- /dev/null +++ b/tools/aapt2/BigBuffer.h @@ -0,0 +1,158 @@ +/* + * 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. + */ + +#ifndef AAPT_BIG_BUFFER_H +#define AAPT_BIG_BUFFER_H + +#include <cstring> +#include <memory> +#include <vector> + +namespace aapt { + +/** + * Inspired by protobuf's ZeroCopyOutputStream, offers blocks of memory + * in which to write without knowing the full size of the entire payload. + * This is essentially a list of memory blocks. As one fills up, another + * block is allocated and appended to the end of the list. + */ +class BigBuffer { +public: + /** + * A contiguous block of allocated memory. + */ + struct Block { + /** + * Pointer to the memory. + */ + std::unique_ptr<uint8_t[]> buffer; + + /** + * Size of memory that is currently occupied. The actual + * allocation may be larger. + */ + size_t size; + + private: + friend class BigBuffer; + + /** + * The size of the memory block allocation. + */ + size_t mBlockSize; + }; + + typedef std::vector<Block>::const_iterator const_iterator; + + /** + * Create a BigBuffer with block allocation sizes + * of blockSize. + */ + BigBuffer(size_t blockSize); + + BigBuffer(const BigBuffer&) = delete; // No copying. + + BigBuffer(BigBuffer&& rhs); + + /** + * Number of occupied bytes in all the allocated blocks. + */ + size_t size() const; + + /** + * Returns a pointer to an array of T, where T is + * a POD type. The elements are zero-initialized. + */ + template <typename T> + T* nextBlock(size_t count = 1); + + /** + * Moves the specified BigBuffer into this one. When this method + * returns, buffer is empty. + */ + void appendBuffer(BigBuffer&& buffer); + + /** + * Pads the block with 'bytes' bytes of zero values. + */ + void pad(size_t bytes); + + /** + * Pads the block so that it aligns on a 4 byte boundary. + */ + void align4(); + + const_iterator begin() const; + const_iterator end() const; + +private: + /** + * Returns a pointer to a buffer of the requested size. + * The buffer is zero-initialized. + */ + void* nextBlockImpl(size_t size); + + size_t mBlockSize; + size_t mSize; + std::vector<Block> mBlocks; +}; + +inline BigBuffer::BigBuffer(size_t blockSize) : mBlockSize(blockSize), mSize(0) { +} + +inline BigBuffer::BigBuffer(BigBuffer&& rhs) : + mBlockSize(rhs.mBlockSize), mSize(rhs.mSize), mBlocks(std::move(rhs.mBlocks)) { +} + +inline size_t BigBuffer::size() const { + return mSize; +} + +template <typename T> +inline T* BigBuffer::nextBlock(size_t count) { + assert(count != 0); + return reinterpret_cast<T*>(nextBlockImpl(sizeof(T) * count)); +} + +inline void BigBuffer::appendBuffer(BigBuffer&& buffer) { + std::move(buffer.mBlocks.begin(), buffer.mBlocks.end(), std::back_inserter(mBlocks)); + mSize += buffer.mSize; + buffer.mBlocks.clear(); + buffer.mSize = 0; +} + +inline void BigBuffer::pad(size_t bytes) { + nextBlock<char>(bytes); +} + +inline void BigBuffer::align4() { + const size_t unaligned = mSize % 4; + if (unaligned != 0) { + pad(4 - unaligned); + } +} + +inline BigBuffer::const_iterator BigBuffer::begin() const { + return mBlocks.begin(); +} + +inline BigBuffer::const_iterator BigBuffer::end() const { + return mBlocks.end(); +} + +} // namespace aapt + +#endif // AAPT_BIG_BUFFER_H |