Home | History | Annotate | Download | only in util
      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 #include "util/BigBuffer.h"
     18 
     19 #include <algorithm>
     20 #include <memory>
     21 #include <vector>
     22 
     23 #include "android-base/logging.h"
     24 
     25 namespace aapt {
     26 
     27 void* BigBuffer::NextBlockImpl(size_t size) {
     28   if (!blocks_.empty()) {
     29     Block& block = blocks_.back();
     30     if (block.block_size_ - block.size >= size) {
     31       void* out_buffer = block.buffer.get() + block.size;
     32       block.size += size;
     33       size_ += size;
     34       return out_buffer;
     35     }
     36   }
     37 
     38   const size_t actual_size = std::max(block_size_, size);
     39 
     40   Block block = {};
     41 
     42   // Zero-allocate the block's buffer.
     43   block.buffer = std::unique_ptr<uint8_t[]>(new uint8_t[actual_size]());
     44   CHECK(block.buffer);
     45 
     46   block.size = size;
     47   block.block_size_ = actual_size;
     48 
     49   blocks_.push_back(std::move(block));
     50   size_ += size;
     51   return blocks_.back().buffer.get();
     52 }
     53 
     54 void* BigBuffer::NextBlock(size_t* out_size) {
     55   if (!blocks_.empty()) {
     56     Block& block = blocks_.back();
     57     if (block.size != block.block_size_) {
     58       void* out_buffer = block.buffer.get() + block.size;
     59       size_t size = block.block_size_ - block.size;
     60       block.size = block.block_size_;
     61       size_ += size;
     62       *out_size = size;
     63       return out_buffer;
     64     }
     65   }
     66 
     67   // Zero-allocate the block's buffer.
     68   Block block = {};
     69   block.buffer = std::unique_ptr<uint8_t[]>(new uint8_t[block_size_]());
     70   CHECK(block.buffer);
     71   block.size = block_size_;
     72   block.block_size_ = block_size_;
     73   blocks_.push_back(std::move(block));
     74   size_ += block_size_;
     75   *out_size = block_size_;
     76   return blocks_.back().buffer.get();
     77 }
     78 
     79 std::string BigBuffer::to_string() const {
     80   std::string result;
     81   for (const Block& block : blocks_) {
     82     result.append(block.buffer.get(), block.buffer.get() + block.size);
     83   }
     84   return result;
     85 }
     86 
     87 }  // namespace aapt
     88