1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef AAPT_BIG_BUFFER_H 18 #define AAPT_BIG_BUFFER_H 19 20 #include <cassert> 21 #include <cstring> 22 #include <memory> 23 #include <type_traits> 24 #include <vector> 25 26 namespace aapt { 27 28 /** 29 * Inspired by protobuf's ZeroCopyOutputStream, offers blocks of memory 30 * in which to write without knowing the full size of the entire payload. 31 * This is essentially a list of memory blocks. As one fills up, another 32 * block is allocated and appended to the end of the list. 33 */ 34 class BigBuffer { 35 public: 36 /** 37 * A contiguous block of allocated memory. 38 */ 39 struct Block { 40 /** 41 * Pointer to the memory. 42 */ 43 std::unique_ptr<uint8_t[]> buffer; 44 45 /** 46 * Size of memory that is currently occupied. The actual 47 * allocation may be larger. 48 */ 49 size_t size; 50 51 private: 52 friend class BigBuffer; 53 54 /** 55 * The size of the memory block allocation. 56 */ 57 size_t mBlockSize; 58 }; 59 60 typedef std::vector<Block>::const_iterator const_iterator; 61 62 /** 63 * Create a BigBuffer with block allocation sizes 64 * of blockSize. 65 */ 66 BigBuffer(size_t blockSize); 67 68 BigBuffer(const BigBuffer&) = delete; // No copying. 69 70 BigBuffer(BigBuffer&& rhs); 71 72 /** 73 * Number of occupied bytes in all the allocated blocks. 74 */ 75 size_t size() const; 76 77 /** 78 * Returns a pointer to an array of T, where T is 79 * a POD type. The elements are zero-initialized. 80 */ 81 template <typename T> 82 T* nextBlock(size_t count = 1); 83 84 /** 85 * Moves the specified BigBuffer into this one. When this method 86 * returns, buffer is empty. 87 */ 88 void appendBuffer(BigBuffer&& buffer); 89 90 /** 91 * Pads the block with 'bytes' bytes of zero values. 92 */ 93 void pad(size_t bytes); 94 95 /** 96 * Pads the block so that it aligns on a 4 byte boundary. 97 */ 98 void align4(); 99 100 const_iterator begin() const; 101 const_iterator end() const; 102 103 private: 104 /** 105 * Returns a pointer to a buffer of the requested size. 106 * The buffer is zero-initialized. 107 */ 108 void* nextBlockImpl(size_t size); 109 110 size_t mBlockSize; 111 size_t mSize; 112 std::vector<Block> mBlocks; 113 }; 114 115 inline BigBuffer::BigBuffer(size_t blockSize) : mBlockSize(blockSize), mSize(0) { 116 } 117 118 inline BigBuffer::BigBuffer(BigBuffer&& rhs) : 119 mBlockSize(rhs.mBlockSize), mSize(rhs.mSize), mBlocks(std::move(rhs.mBlocks)) { 120 } 121 122 inline size_t BigBuffer::size() const { 123 return mSize; 124 } 125 126 template <typename T> 127 inline T* BigBuffer::nextBlock(size_t count) { 128 static_assert(std::is_standard_layout<T>::value, "T must be standard_layout type"); 129 assert(count != 0); 130 return reinterpret_cast<T*>(nextBlockImpl(sizeof(T) * count)); 131 } 132 133 inline void BigBuffer::appendBuffer(BigBuffer&& buffer) { 134 std::move(buffer.mBlocks.begin(), buffer.mBlocks.end(), std::back_inserter(mBlocks)); 135 mSize += buffer.mSize; 136 buffer.mBlocks.clear(); 137 buffer.mSize = 0; 138 } 139 140 inline void BigBuffer::pad(size_t bytes) { 141 nextBlock<char>(bytes); 142 } 143 144 inline void BigBuffer::align4() { 145 const size_t unaligned = mSize % 4; 146 if (unaligned != 0) { 147 pad(4 - unaligned); 148 } 149 } 150 151 inline BigBuffer::const_iterator BigBuffer::begin() const { 152 return mBlocks.begin(); 153 } 154 155 inline BigBuffer::const_iterator BigBuffer::end() const { 156 return mBlocks.end(); 157 } 158 159 } // namespace aapt 160 161 #endif // AAPT_BIG_BUFFER_H 162