16f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 26f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 36f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 46f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 56f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * you may not use this file except in compliance with the License. 66f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * You may obtain a copy of the License at 76f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 86f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 96f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Unless required by applicable law or agreed to in writing, software 116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * See the License for the specific language governing permissions and 146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * limitations under the License. 156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#ifndef AAPT_BIG_BUFFER_H 186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#define AAPT_BIG_BUFFER_H 196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <cstring> 216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <memory> 22c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski#include <string> 231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <type_traits> 246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <vector> 256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 26ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/logging.h" 27ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/macros.h" 28ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Inspired by protobuf's ZeroCopyOutputStream, offers blocks of memory 336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * in which to write without knowing the full size of the entire payload. 346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * This is essentially a list of memory blocks. As one fills up, another 356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * block is allocated and appended to the end of the list. 366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiclass BigBuffer { 38cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public: 39cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 40cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * A contiguous block of allocated memory. 41cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 42cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski struct Block { 436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski /** 44cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Pointer to the memory. 456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 46cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<uint8_t[]> buffer; 4721efb6827cede06c2ab708de6cdb64d052dddcceAdam Lesinski 4821efb6827cede06c2ab708de6cdb64d052dddcceAdam Lesinski /** 49cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Size of memory that is currently occupied. The actual 50cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * allocation may be larger. 5121efb6827cede06c2ab708de6cdb64d052dddcceAdam Lesinski */ 52cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski size_t size; 5321efb6827cede06c2ab708de6cdb64d052dddcceAdam Lesinski 54cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private: 55cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski friend class BigBuffer; 566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski /** 58cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * The size of the memory block allocation. 596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 60ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t block_size_; 61cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski }; 62cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 63cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski typedef std::vector<Block>::const_iterator const_iterator; 64cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 65cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 66cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Create a BigBuffer with block allocation sizes 67ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * of block_size. 68cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 69ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski explicit BigBuffer(size_t block_size); 70cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 71cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski BigBuffer(BigBuffer&& rhs); 72cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 73cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 74cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Number of occupied bytes in all the allocated blocks. 75cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 76cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski size_t size() const; 77cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 78cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 79cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Returns a pointer to an array of T, where T is 80cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * a POD type. The elements are zero-initialized. 81cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 82cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski template <typename T> 83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski T* NextBlock(size_t count = 1); 84cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 85cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * Returns the next block available and puts the size in out_count. 87cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * This is useful for grabbing blocks where the size doesn't matter. 88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * Use BackUp() to give back any bytes that were not used. 89cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski void* NextBlock(size_t* out_count); 91cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 92cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * Backs up count bytes. This must only be called after NextBlock() 94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * and can not be larger than sizeof(T) * count of the last NextBlock() 95cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * call. 96cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski void BackUp(size_t count); 98cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 99cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 100cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Moves the specified BigBuffer into this one. When this method 101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * returns, buffer is empty. 102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski void AppendBuffer(BigBuffer&& buffer); 104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 106cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Pads the block with 'bytes' bytes of zero values. 107cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski void Pad(size_t bytes); 109cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 110cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Pads the block so that it aligns on a 4 byte boundary. 112cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 113ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski void Align4(); 114cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t block_size() const; 116cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 117cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const_iterator begin() const; 118cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const_iterator end() const; 119cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 120c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::string to_string() const; 121c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 122cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private: 123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DISALLOW_COPY_AND_ASSIGN(BigBuffer); 124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 125cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski /** 126cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Returns a pointer to a buffer of the requested size. 127cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * The buffer is zero-initialized. 128cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski */ 129ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski void* NextBlockImpl(size_t size); 130cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 131ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t block_size_; 132ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t size_; 133ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<Block> blocks_; 1346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 1356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 136ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiinline BigBuffer::BigBuffer(size_t block_size) 137ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski : block_size_(block_size), size_(0) {} 1386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 139cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinskiinline BigBuffer::BigBuffer(BigBuffer&& rhs) 140ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski : block_size_(rhs.block_size_), 141ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_(rhs.size_), 142ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski blocks_(std::move(rhs.blocks_)) {} 1436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiinline size_t BigBuffer::size() const { return size_; } 1456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 146ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiinline size_t BigBuffer::block_size() const { return block_size_; } 14721efb6827cede06c2ab708de6cdb64d052dddcceAdam Lesinski 1486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T> 149ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiinline T* BigBuffer::NextBlock(size_t count) { 150cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski static_assert(std::is_standard_layout<T>::value, 151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "T must be standard_layout type"); 152ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(count != 0); 153ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return reinterpret_cast<T*>(NextBlockImpl(sizeof(T) * count)); 1546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiinline void BigBuffer::BackUp(size_t count) { 157ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Block& block = blocks_.back(); 158cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski block.size -= count; 159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_ -= count; 16021efb6827cede06c2ab708de6cdb64d052dddcceAdam Lesinski} 16121efb6827cede06c2ab708de6cdb64d052dddcceAdam Lesinski 162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiinline void BigBuffer::AppendBuffer(BigBuffer&& buffer) { 163ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::move(buffer.blocks_.begin(), buffer.blocks_.end(), 164ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::back_inserter(blocks_)); 165ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_ += buffer.size_; 166ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski buffer.blocks_.clear(); 167ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski buffer.size_ = 0; 1686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 170ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiinline void BigBuffer::Pad(size_t bytes) { NextBlock<char>(bytes); } 1716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 172ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiinline void BigBuffer::Align4() { 173ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const size_t unaligned = size_ % 4; 174cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (unaligned != 0) { 175ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Pad(4 - unaligned); 176cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline BigBuffer::const_iterator BigBuffer::begin() const { 180ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return blocks_.begin(); 1816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline BigBuffer::const_iterator BigBuffer::end() const { 184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return blocks_.end(); 1856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 187cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} // namespace aapt 1886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 189cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski#endif // AAPT_BIG_BUFFER_H 190