From 159ee1528e0870555bf1bac8f24795d84c223a56 Mon Sep 17 00:00:00 2001
From: Khem Raj <raj.khem@gmail.com>
Date: Thu, 2 Jan 2020 17:13:55 -0800
Subject: [PATCH] chromium: Move CharAllocator definition to a header file

Fixes
error: invalid application of 'sizeof' to an incomplete type 'cc::ListContainerHelper::CharAllocator'

Signed-off-by: Khem Raj <raj.khem@gmail.com>
---
 chromium/cc/base/list_container_helper.cc | 251 ---------------------
 chromium/cc/base/list_container_helper.h  | 255 ++++++++++++++++++++++
 2 files changed, 255 insertions(+), 251 deletions(-)

diff --git a/chromium/cc/base/list_container_helper.cc b/chromium/cc/base/list_container_helper.cc
index 7b594b4a458..9dae1c360c4 100644
--- a/chromium/cc/base/list_container_helper.cc
+++ b/chromium/cc/base/list_container_helper.cc
@@ -13,259 +13,8 @@
 #include "base/check_op.h"
 #include "base/memory/aligned_memory.h"
 
-namespace {
-const size_t kDefaultNumElementTypesToReserve = 32;
-}  // namespace
-
 namespace cc {
 
-// CharAllocator
-////////////////////////////////////////////////////
-// This class deals only with char* and void*. It does allocation and passing
-// out raw pointers, as well as memory deallocation when being destroyed.
-class ListContainerHelper::CharAllocator {
- public:
-  // CharAllocator::InnerList
-  /////////////////////////////////////////////
-  // This class holds the raw memory chunk, as well as information about its
-  // size and availability.
-  struct InnerList {
-    InnerList(const InnerList&) = delete;
-    InnerList& operator=(const InnerList&) = delete;
-
-    std::unique_ptr<char[], base::AlignedFreeDeleter> data;
-    // The number of elements in total the memory can hold. The difference
-    // between capacity and size is the how many more elements this list can
-    // hold.
-    size_t capacity;
-    // The number of elements have been put into this list.
-    size_t size;
-    // The size of each element is in bytes. This is used to move from between
-    // elements' memory locations.
-    size_t step;
-
-    InnerList() : capacity(0), size(0), step(0) {}
-
-    void Erase(char* position) {
-      // Confident that destructor is called by caller of this function. Since
-      // CharAllocator does not handle construction after
-      // allocation, it doesn't handle desctrution before deallocation.
-      DCHECK_LE(position, LastElement());
-      DCHECK_GE(position, Begin());
-      char* start = position + step;
-      std::copy(start, End(), position);
-
-      --size;
-      // Decrease capacity to avoid creating not full not last InnerList.
-      --capacity;
-    }
-
-    void InsertBefore(size_t alignment, char** position, size_t count) {
-      DCHECK_LE(*position, LastElement() + step);
-      DCHECK_GE(*position, Begin());
-
-      // Adjust the size and capacity
-      size_t old_size = size;
-      size += count;
-      capacity = size;
-
-      // Allocate the new data and update the iterator's pointer.
-      std::unique_ptr<char[], base::AlignedFreeDeleter> new_data(
-          static_cast<char*>(base::AlignedAlloc(size * step, alignment)));
-      size_t position_offset = *position - Begin();
-      *position = new_data.get() + position_offset;
-
-      // Copy the data before the inserted segment
-      memcpy(new_data.get(), data.get(), position_offset);
-      // Copy the data after the inserted segment.
-      memcpy(new_data.get() + position_offset + count * step,
-             data.get() + position_offset, old_size * step - position_offset);
-      data = std::move(new_data);
-    }
-
-    bool IsEmpty() const { return !size; }
-    bool IsFull() { return capacity == size; }
-    size_t NumElementsAvailable() const { return capacity - size; }
-
-    void* AddElement() {
-      DCHECK_LT(size, capacity);
-      ++size;
-      return LastElement();
-    }
-
-    void RemoveLast() {
-      DCHECK(!IsEmpty());
-      --size;
-    }
-
-    char* Begin() const { return data.get(); }
-    char* End() const { return data.get() + size * step; }
-    char* LastElement() const { return data.get() + (size - 1) * step; }
-    char* ElementAt(size_t index) const { return data.get() + index * step; }
-  };
-
-  CharAllocator(size_t alignment, size_t element_size, size_t element_count)
-      // base::AlignedAlloc does not accept alignment less than sizeof(void*).
-      : alignment_(std::max(sizeof(void*), alignment)),
-        element_size_(element_size),
-        size_(0),
-        last_list_index_(0),
-        last_list_(nullptr) {
-    // If this fails, then alignment of elements after the first could be wrong,
-    // and we need to pad sizes to fix that.
-    DCHECK_EQ(element_size % alignment, 0u);
-    AllocateNewList(element_count > 0 ? element_count
-                                      : kDefaultNumElementTypesToReserve);
-    last_list_ = storage_[last_list_index_].get();
-  }
-
-  CharAllocator(const CharAllocator&) = delete;
-  ~CharAllocator() = default;
-
-  CharAllocator& operator=(const CharAllocator&) = delete;
-
-  void* Allocate() {
-    if (last_list_->IsFull()) {
-      // Only allocate a new list if there isn't a spare one still there from
-      // previous usage.
-      if (last_list_index_ + 1 >= storage_.size())
-        AllocateNewList(last_list_->capacity * 2);
-
-      ++last_list_index_;
-      last_list_ = storage_[last_list_index_].get();
-    }
-
-    ++size_;
-    return last_list_->AddElement();
-  }
-
-  size_t alignment() const { return alignment_; }
-  size_t element_size() const { return element_size_; }
-  size_t list_count() const { return storage_.size(); }
-  size_t size() const { return size_; }
-  bool IsEmpty() const { return size() == 0; }
-
-  size_t Capacity() const {
-    size_t capacity_sum = 0;
-    for (const auto& inner_list : storage_)
-      capacity_sum += inner_list->capacity;
-    return capacity_sum;
-  }
-
-  void Clear() {
-    // Remove all except for the first InnerList.
-    DCHECK(!storage_.empty());
-    storage_.erase(storage_.begin() + 1, storage_.end());
-    last_list_index_ = 0;
-    last_list_ = storage_[0].get();
-    last_list_->size = 0;
-    size_ = 0;
-  }
-
-  void RemoveLast() {
-    DCHECK(!IsEmpty());
-    last_list_->RemoveLast();
-    if (last_list_->IsEmpty() && last_list_index_ > 0) {
-      --last_list_index_;
-      last_list_ = storage_[last_list_index_].get();
-
-      // If there are now two empty inner lists, free one of them.
-      if (last_list_index_ + 2 < storage_.size())
-        storage_.pop_back();
-    }
-    --size_;
-  }
-
-  void Erase(PositionInCharAllocator* position) {
-    DCHECK_EQ(this, position->ptr_to_container);
-
-    // Update |position| to point to the element after the erased element.
-    InnerList* list = storage_[position->vector_index].get();
-    char* item_iterator = position->item_iterator;
-    if (item_iterator == list->LastElement())
-      position->Increment();
-
-    list->Erase(item_iterator);
-    // TODO(weiliangc): Free the InnerList if it is empty.
-    --size_;
-  }
-
-  void InsertBefore(ListContainerHelper::Iterator* position, size_t count) {
-    if (!count)
-      return;
-
-    // If |position| is End(), then append |count| elements at the end. This
-    // will happen to not invalidate any iterators or memory.
-    if (!position->item_iterator) {
-      // Set |position| to be the first inserted element.
-      Allocate();
-      position->vector_index = storage_.size() - 1;
-      position->item_iterator = storage_[position->vector_index]->LastElement();
-      // Allocate the rest.
-      for (size_t i = 1; i < count; ++i)
-        Allocate();
-    } else {
-      storage_[position->vector_index]->InsertBefore(
-          alignment_, &position->item_iterator, count);
-      size_ += count;
-    }
-  }
-
-  InnerList* InnerListById(size_t id) const {
-    DCHECK_LT(id, storage_.size());
-    return storage_[id].get();
-  }
-
-  size_t FirstInnerListId() const {
-    // |size_| > 0 means that at least one vector in |storage_| will be
-    // non-empty.
-    DCHECK_GT(size_, 0u);
-    size_t id = 0;
-    while (storage_[id]->size == 0)
-      ++id;
-    return id;
-  }
-
-  size_t LastInnerListId() const {
-    // |size_| > 0 means that at least one vector in |storage_| will be
-    // non-empty.
-    DCHECK_GT(size_, 0u);
-    size_t id = storage_.size() - 1;
-    while (storage_[id]->size == 0)
-      --id;
-    return id;
-  }
-
-  size_t NumAvailableElementsInLastList() const {
-    return last_list_->NumElementsAvailable();
-  }
-
- private:
-  void AllocateNewList(size_t list_size) {
-    std::unique_ptr<InnerList> new_list(new InnerList);
-    new_list->capacity = list_size;
-    new_list->size = 0;
-    new_list->step = element_size_;
-    new_list->data.reset(static_cast<char*>(
-        base::AlignedAlloc(list_size * element_size_, alignment_)));
-    storage_.push_back(std::move(new_list));
-  }
-
-  std::vector<std::unique_ptr<InnerList>> storage_;
-  const size_t alignment_;
-  const size_t element_size_;
-
-  // The number of elements in the list.
-  size_t size_;
-
-  // The index of the last list to have had elements added to it, or the only
-  // list if the container has not had elements added since being cleared.
-  size_t last_list_index_;
-
-  // This is equivalent to |storage_[last_list_index_]|.
-  InnerList* last_list_;
-};
-
 // PositionInCharAllocator
 //////////////////////////////////////////////////////
 ListContainerHelper::PositionInCharAllocator::PositionInCharAllocator(
diff --git a/chromium/cc/base/list_container_helper.h b/chromium/cc/base/list_container_helper.h
index 31658bc8486..9e65013cbdb 100644
--- a/chromium/cc/base/list_container_helper.h
+++ b/chromium/cc/base/list_container_helper.h
@@ -8,9 +8,17 @@
 #include <stddef.h>
 
 #include <memory>
+#include <algorithm>
+#include <vector>
 
+#include "base/logging.h"
+#include "base/memory/aligned_memory.h"
 #include "cc/base/base_export.h"
 
+namespace {
+const size_t kDefaultNumElementTypesToReserve = 32;
+}  // namespace
+
 namespace cc {
 
 // Helper class for ListContainer non-templated logic. All methods are private,
@@ -174,6 +182,253 @@ class CC_BASE_EXPORT ListContainerHelper final {
   std::unique_ptr<CharAllocator> data_;
 };
 
+// CharAllocator
+////////////////////////////////////////////////////
+// This class deals only with char* and void*. It does allocation and passing
+// out raw pointers, as well as memory deallocation when being destroyed.
+class ListContainerHelper::CharAllocator {
+ public:
+  // CharAllocator::InnerList
+  /////////////////////////////////////////////
+  // This class holds the raw memory chunk, as well as information about its
+  // size and availability.
+  struct InnerList {
+    InnerList(const InnerList&) = delete;
+    InnerList& operator=(const InnerList&) = delete;
+
+    std::unique_ptr<char[], base::AlignedFreeDeleter> data;
+    // The number of elements in total the memory can hold. The difference
+    // between capacity and size is the how many more elements this list can
+    // hold.
+    size_t capacity;
+    // The number of elements have been put into this list.
+    size_t size;
+    // The size of each element is in bytes. This is used to move from between
+    // elements' memory locations.
+    size_t step;
+
+    InnerList() : capacity(0), size(0), step(0) {}
+
+    void Erase(char* position) {
+      // Confident that destructor is called by caller of this function. Since
+      // CharAllocator does not handle construction after
+      // allocation, it doesn't handle desctrution before deallocation.
+      DCHECK_LE(position, LastElement());
+      DCHECK_GE(position, Begin());
+      char* start = position + step;
+      std::copy(start, End(), position);
+
+      --size;
+      // Decrease capacity to avoid creating not full not last InnerList.
+      --capacity;
+    }
+
+    void InsertBefore(size_t alignment, char** position, size_t count) {
+      DCHECK_LE(*position, LastElement() + step);
+      DCHECK_GE(*position, Begin());
+
+      // Adjust the size and capacity
+      size_t old_size = size;
+      size += count;
+      capacity = size;
+
+      // Allocate the new data and update the iterator's pointer.
+      std::unique_ptr<char[], base::AlignedFreeDeleter> new_data(
+          static_cast<char*>(base::AlignedAlloc(size * step, alignment)));
+      size_t position_offset = *position - Begin();
+      *position = new_data.get() + position_offset;
+
+      // Copy the data before the inserted segment
+      memcpy(new_data.get(), data.get(), position_offset);
+      // Copy the data after the inserted segment.
+      memcpy(new_data.get() + position_offset + count * step,
+             data.get() + position_offset, old_size * step - position_offset);
+      data = std::move(new_data);
+    }
+
+    bool IsEmpty() const { return !size; }
+    bool IsFull() { return capacity == size; }
+    size_t NumElementsAvailable() const { return capacity - size; }
+
+    void* AddElement() {
+      DCHECK_LT(size, capacity);
+      ++size;
+      return LastElement();
+    }
+
+    void RemoveLast() {
+      DCHECK(!IsEmpty());
+      --size;
+    }
+
+    char* Begin() const { return data.get(); }
+    char* End() const { return data.get() + size * step; }
+    char* LastElement() const { return data.get() + (size - 1) * step; }
+    char* ElementAt(size_t index) const { return data.get() + index * step; }
+  };
+
+  CharAllocator(size_t alignment, size_t element_size, size_t element_count)
+      // base::AlignedAlloc does not accept alignment less than sizeof(void*).
+      : alignment_(std::max(sizeof(void*), alignment)),
+        element_size_(element_size),
+        size_(0),
+        last_list_index_(0),
+        last_list_(nullptr) {
+    // If this fails, then alignment of elements after the first could be wrong,
+    // and we need to pad sizes to fix that.
+    DCHECK_EQ(element_size % alignment, 0u);
+    AllocateNewList(element_count > 0 ? element_count
+                                      : kDefaultNumElementTypesToReserve);
+    last_list_ = storage_[last_list_index_].get();
+  }
+
+  CharAllocator(const CharAllocator&) = delete;
+  ~CharAllocator() = default;
+
+  CharAllocator& operator=(const CharAllocator&) = delete;
+
+  void* Allocate() {
+    if (last_list_->IsFull()) {
+      // Only allocate a new list if there isn't a spare one still there from
+      // previous usage.
+      if (last_list_index_ + 1 >= storage_.size())
+        AllocateNewList(last_list_->capacity * 2);
+
+      ++last_list_index_;
+      last_list_ = storage_[last_list_index_].get();
+    }
+
+    ++size_;
+    return last_list_->AddElement();
+  }
+
+  size_t alignment() const { return alignment_; }
+  size_t element_size() const { return element_size_; }
+  size_t list_count() const { return storage_.size(); }
+  size_t size() const { return size_; }
+  bool IsEmpty() const { return size() == 0; }
+
+  size_t Capacity() const {
+    size_t capacity_sum = 0;
+    for (const auto& inner_list : storage_)
+      capacity_sum += inner_list->capacity;
+    return capacity_sum;
+  }
+
+  void Clear() {
+    // Remove all except for the first InnerList.
+    DCHECK(!storage_.empty());
+    storage_.erase(storage_.begin() + 1, storage_.end());
+    last_list_index_ = 0;
+    last_list_ = storage_[0].get();
+    last_list_->size = 0;
+    size_ = 0;
+  }
+
+  void RemoveLast() {
+    DCHECK(!IsEmpty());
+    last_list_->RemoveLast();
+    if (last_list_->IsEmpty() && last_list_index_ > 0) {
+      --last_list_index_;
+      last_list_ = storage_[last_list_index_].get();
+
+      // If there are now two empty inner lists, free one of them.
+      if (last_list_index_ + 2 < storage_.size())
+        storage_.pop_back();
+    }
+    --size_;
+  }
+
+  void Erase(PositionInCharAllocator* position) {
+    DCHECK_EQ(this, position->ptr_to_container);
+
+    // Update |position| to point to the element after the erased element.
+    InnerList* list = storage_[position->vector_index].get();
+    char* item_iterator = position->item_iterator;
+    if (item_iterator == list->LastElement())
+      position->Increment();
+
+    list->Erase(item_iterator);
+    // TODO(weiliangc): Free the InnerList if it is empty.
+    --size_;
+  }
+
+  void InsertBefore(ListContainerHelper::Iterator* position, size_t count) {
+    if (!count)
+      return;
+
+    // If |position| is End(), then append |count| elements at the end. This
+    // will happen to not invalidate any iterators or memory.
+    if (!position->item_iterator) {
+      // Set |position| to be the first inserted element.
+      Allocate();
+      position->vector_index = storage_.size() - 1;
+      position->item_iterator = storage_[position->vector_index]->LastElement();
+      // Allocate the rest.
+      for (size_t i = 1; i < count; ++i)
+        Allocate();
+    } else {
+      storage_[position->vector_index]->InsertBefore(
+          alignment_, &position->item_iterator, count);
+      size_ += count;
+    }
+  }
+
+  InnerList* InnerListById(size_t id) const {
+    DCHECK_LT(id, storage_.size());
+    return storage_[id].get();
+  }
+
+  size_t FirstInnerListId() const {
+    // |size_| > 0 means that at least one vector in |storage_| will be
+    // non-empty.
+    DCHECK_GT(size_, 0u);
+    size_t id = 0;
+    while (storage_[id]->size == 0)
+      ++id;
+    return id;
+  }
+
+  size_t LastInnerListId() const {
+    // |size_| > 0 means that at least one vector in |storage_| will be
+    // non-empty.
+    DCHECK_GT(size_, 0u);
+    size_t id = storage_.size() - 1;
+    while (storage_[id]->size == 0)
+      --id;
+    return id;
+  }
+
+  size_t NumAvailableElementsInLastList() const {
+    return last_list_->NumElementsAvailable();
+  }
+
+ private:
+  void AllocateNewList(size_t list_size) {
+    std::unique_ptr<InnerList> new_list(new InnerList);
+    new_list->capacity = list_size;
+    new_list->size = 0;
+    new_list->step = element_size_;
+    new_list->data.reset(static_cast<char*>(
+        base::AlignedAlloc(list_size * element_size_, alignment_)));
+    storage_.push_back(std::move(new_list));
+  }
+
+  std::vector<std::unique_ptr<InnerList>> storage_;
+  const size_t alignment_;
+  const size_t element_size_;
+
+  // The number of elements in the list.
+  size_t size_;
+
+  // The index of the last list to have had elements added to it, or the only
+  // list if the container has not had elements added since being cleared.
+  size_t last_list_index_;
+
+  // This is equivalent to |storage_[last_list_index_]|.
+  InnerList* last_list_;
+};
+
 }  // namespace cc
 
 #endif  // CC_BASE_LIST_CONTAINER_HELPER_H_
