/*
 * 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 <string>
#include <type_traits>
#include <vector>

#include "android-base/logging.h"
#include "android-base/macros.h"

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 block_size_;
  };

  typedef std::vector<Block>::const_iterator const_iterator;

  /**
   * Create a BigBuffer with block allocation sizes
   * of block_size.
   */
  explicit BigBuffer(size_t block_size);

  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);

  /**
   * Returns the next block available and puts the size in out_count.
   * This is useful for grabbing blocks where the size doesn't matter.
   * Use BackUp() to give back any bytes that were not used.
   */
  void* NextBlock(size_t* out_count);

  /**
   * Backs up count bytes. This must only be called after NextBlock()
   * and can not be larger than sizeof(T) * count of the last NextBlock()
   * call.
   */
  void BackUp(size_t count);

  /**
   * 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();

  size_t block_size() const;

  const_iterator begin() const;
  const_iterator end() const;

  std::string to_string() const;

 private:
  DISALLOW_COPY_AND_ASSIGN(BigBuffer);

  /**
   * Returns a pointer to a buffer of the requested size.
   * The buffer is zero-initialized.
   */
  void* NextBlockImpl(size_t size);

  size_t block_size_;
  size_t size_;
  std::vector<Block> blocks_;
};

inline BigBuffer::BigBuffer(size_t block_size)
    : block_size_(block_size), size_(0) {}

inline BigBuffer::BigBuffer(BigBuffer&& rhs)
    : block_size_(rhs.block_size_),
      size_(rhs.size_),
      blocks_(std::move(rhs.blocks_)) {}

inline size_t BigBuffer::size() const { return size_; }

inline size_t BigBuffer::block_size() const { return block_size_; }

template <typename T>
inline T* BigBuffer::NextBlock(size_t count) {
  static_assert(std::is_standard_layout<T>::value,
                "T must be standard_layout type");
  CHECK(count != 0);
  return reinterpret_cast<T*>(NextBlockImpl(sizeof(T) * count));
}

inline void BigBuffer::BackUp(size_t count) {
  Block& block = blocks_.back();
  block.size -= count;
  size_ -= count;
}

inline void BigBuffer::AppendBuffer(BigBuffer&& buffer) {
  std::move(buffer.blocks_.begin(), buffer.blocks_.end(),
            std::back_inserter(blocks_));
  size_ += buffer.size_;
  buffer.blocks_.clear();
  buffer.size_ = 0;
}

inline void BigBuffer::Pad(size_t bytes) { NextBlock<char>(bytes); }

inline void BigBuffer::Align4() {
  const size_t unaligned = size_ % 4;
  if (unaligned != 0) {
    Pad(4 - unaligned);
  }
}

inline BigBuffer::const_iterator BigBuffer::begin() const {
  return blocks_.begin();
}

inline BigBuffer::const_iterator BigBuffer::end() const {
  return blocks_.end();
}

}  // namespace aapt

#endif  // AAPT_BIG_BUFFER_H
