Add ICU message format support
[chromium-blink-merge.git] / cc / base / list_container.h
blobae7afa92e5b5999c8a124c418ff9b33a90028115
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CC_BASE_LIST_CONTAINER_H_
6 #define CC_BASE_LIST_CONTAINER_H_
8 #include "base/logging.h"
9 #include "base/macros.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "cc/base/cc_export.h"
13 namespace cc {
15 // ListContainer is a container type that handles allocating contiguous memory
16 // for new elements and traversing through elements with either iterator or
17 // reverse iterator. Since this container hands out raw pointers of its
18 // elements, it is very important that this container never reallocate its
19 // memory so those raw pointer will continue to be valid. This class is used to
20 // contain SharedQuadState or DrawQuad. Since the size of each DrawQuad varies,
21 // to hold DrawQuads, the allocations size of each element in this class is
22 // LargestDrawQuadSize while BaseElementType is DrawQuad.
24 // Base class for non-templated logic. All methods are protected, and only
25 // exposed by ListContainer<BaseElementType>.
26 // For usage, see comments in ListContainer.
27 class CC_EXPORT ListContainerBase {
28 protected:
29 explicit ListContainerBase(size_t max_size_for_derived_class);
30 ListContainerBase(size_t max_size_for_derived_class,
31 size_t num_of_elements_to_reserve_for);
32 ~ListContainerBase();
34 // This class deals only with char* and void*. It does allocation and passing
35 // out raw pointers, as well as memory deallocation when being destroyed.
36 class ListContainerCharAllocator;
38 // This class points to a certain position inside memory of
39 // ListContainerCharAllocator. It is a base class for ListContainer iterators.
40 struct CC_EXPORT PositionInListContainerCharAllocator {
41 ListContainerCharAllocator* ptr_to_container;
42 size_t vector_index;
43 char* item_iterator;
45 PositionInListContainerCharAllocator(
46 const PositionInListContainerCharAllocator& other);
48 PositionInListContainerCharAllocator(ListContainerCharAllocator* container,
49 size_t vector_ind,
50 char* item_iter);
52 bool operator==(const PositionInListContainerCharAllocator& other) const;
53 bool operator!=(const PositionInListContainerCharAllocator& other) const;
55 PositionInListContainerCharAllocator Increment();
56 PositionInListContainerCharAllocator ReverseIncrement();
59 // Iterator classes that can be used to access data.
60 /////////////////////////////////////////////////////////////////
61 class CC_EXPORT Iterator : public PositionInListContainerCharAllocator {
62 // This class is only defined to forward iterate through
63 // ListContainerCharAllocator.
64 public:
65 Iterator(ListContainerCharAllocator* container,
66 size_t vector_ind,
67 char* item_iter,
68 size_t index);
69 ~Iterator();
71 size_t index() const;
73 protected:
74 // This is used to track how many increment has happened since begin(). It
75 // is used to avoid double increment at places an index reference is
76 // needed. For iterator this means begin() corresponds to index 0 and end()
77 // corresponds to index |size|.
78 size_t index_;
81 class CC_EXPORT ConstIterator : public PositionInListContainerCharAllocator {
82 // This class is only defined to forward iterate through
83 // ListContainerCharAllocator.
84 public:
85 ConstIterator(ListContainerCharAllocator* container,
86 size_t vector_ind,
87 char* item_iter,
88 size_t index);
89 ConstIterator(const Iterator& other); // NOLINT
90 ~ConstIterator();
92 size_t index() const;
94 protected:
95 // This is used to track how many increment has happened since begin(). It
96 // is used to avoid double increment at places an index reference is
97 // needed. For iterator this means begin() corresponds to index 0 and end()
98 // corresponds to index |size|.
99 size_t index_;
102 class CC_EXPORT ReverseIterator
103 : public PositionInListContainerCharAllocator {
104 // This class is only defined to reverse iterate through
105 // ListContainerCharAllocator.
106 public:
107 ReverseIterator(ListContainerCharAllocator* container,
108 size_t vector_ind,
109 char* item_iter,
110 size_t index);
111 ~ReverseIterator();
113 size_t index() const;
115 protected:
116 // This is used to track how many increment has happened since rbegin(). It
117 // is used to avoid double increment at places an index reference is
118 // needed. For reverse iterator this means rbegin() corresponds to index 0
119 // and rend() corresponds to index |size|.
120 size_t index_;
123 class CC_EXPORT ConstReverseIterator
124 : public PositionInListContainerCharAllocator {
125 // This class is only defined to reverse iterate through
126 // ListContainerCharAllocator.
127 public:
128 ConstReverseIterator(ListContainerCharAllocator* container,
129 size_t vector_ind,
130 char* item_iter,
131 size_t index);
132 ConstReverseIterator(const ReverseIterator& other); // NOLINT
133 ~ConstReverseIterator();
135 size_t index() const;
137 protected:
138 // This is used to track how many increment has happened since rbegin(). It
139 // is used to avoid double increment at places an index reference is
140 // needed. For reverse iterator this means rbegin() corresponds to index 0
141 // and rend() corresponds to index |size|.
142 size_t index_;
145 // Unlike the ListContainer methods, these do not invoke element destructors.
146 void RemoveLast();
147 void EraseAndInvalidateAllPointers(Iterator position);
149 ConstReverseIterator crbegin() const;
150 ConstReverseIterator crend() const;
151 ReverseIterator rbegin();
152 ReverseIterator rend();
153 ConstIterator cbegin() const;
154 ConstIterator cend() const;
155 Iterator begin();
156 Iterator end();
158 Iterator IteratorAt(size_t index);
159 ConstIterator IteratorAt(size_t index) const;
161 size_t size() const;
162 bool empty() const;
164 size_t MaxSizeForDerivedClass() const;
166 size_t GetCapacityInBytes() const;
168 // Unlike the ListContainer method, this one does not invoke element
169 // destructors.
170 void clear();
172 size_t AvailableSizeWithoutAnotherAllocationForTesting() const;
174 // Hands out memory location for an element at the end of data structure.
175 void* Allocate(size_t size_of_actual_element_in_bytes);
177 scoped_ptr<ListContainerCharAllocator> data_;
179 private:
180 DISALLOW_COPY_AND_ASSIGN(ListContainerBase);
183 template <class BaseElementType>
184 class ListContainer : public ListContainerBase {
185 public:
186 // BaseElementType is the type of raw pointers this class hands out; however,
187 // its derived classes might require different memory sizes.
188 // max_size_for_derived_class the largest memory size required for all the
189 // derived classes to use for allocation.
190 explicit ListContainer(size_t max_size_for_derived_class)
191 : ListContainerBase(max_size_for_derived_class) {}
193 // This constructor omits input variable for max_size_for_derived_class. This
194 // is used when there is no derived classes from BaseElementType we need to
195 // worry about, and allocation size is just sizeof(BaseElementType).
196 ListContainer() : ListContainerBase(sizeof(BaseElementType)) {}
198 // This constructor reserves the requested memory up front so only single
199 // allocation is needed. When num_of_elements_to_reserve_for is zero, use the
200 // default size.
201 ListContainer(size_t max_size_for_derived_class,
202 size_t num_of_elements_to_reserve_for)
203 : ListContainerBase(max_size_for_derived_class,
204 num_of_elements_to_reserve_for) {}
206 ~ListContainer() {
207 for (Iterator i = begin(); i != end(); ++i) {
208 i->~BaseElementType();
212 class Iterator;
213 class ConstIterator;
214 class ReverseIterator;
215 class ConstReverseIterator;
217 // Removes the last element of the list and makes its space available for
218 // allocation.
219 void RemoveLast() {
220 DCHECK(!empty());
221 back()->~BaseElementType();
222 ListContainerBase::RemoveLast();
225 // When called, all raw pointers that have been handed out are no longer
226 // valid. Use with caution.
227 // This function does not deallocate memory.
228 void EraseAndInvalidateAllPointers(Iterator position) {
229 BaseElementType* item = *position;
230 item->~BaseElementType();
231 ListContainerBase::EraseAndInvalidateAllPointers(position);
234 ConstReverseIterator crbegin() const {
235 return ConstReverseIterator(ListContainerBase::crbegin());
237 ConstReverseIterator crend() const {
238 return ConstReverseIterator(ListContainerBase::crend());
240 ConstReverseIterator rbegin() const { return crbegin(); }
241 ConstReverseIterator rend() const { return crend(); }
242 ReverseIterator rbegin() {
243 return ReverseIterator(ListContainerBase::rbegin());
245 ReverseIterator rend() { return ReverseIterator(ListContainerBase::rend()); }
246 ConstIterator cbegin() const {
247 return ConstIterator(ListContainerBase::cbegin());
249 ConstIterator cend() const {
250 return ConstIterator(ListContainerBase::cend());
252 ConstIterator begin() const { return cbegin(); }
253 ConstIterator end() const { return cend(); }
254 Iterator begin() { return Iterator(ListContainerBase::begin()); }
255 Iterator end() { return Iterator(ListContainerBase::end()); }
257 // TODO(weiliangc): front(), back() and ElementAt() function should return
258 // reference, consistent with container-of-object.
259 BaseElementType* front() { return *begin(); }
260 BaseElementType* back() { return *rbegin(); }
261 const BaseElementType* front() const { return *begin(); }
262 const BaseElementType* back() const { return *rbegin(); }
264 BaseElementType* ElementAt(size_t index) {
265 return *Iterator(IteratorAt(index));
267 const BaseElementType* ElementAt(size_t index) const {
268 return *ConstIterator(IteratorAt(index));
271 // Take in derived element type and construct it at location generated by
272 // Allocate().
273 template <typename DerivedElementType>
274 DerivedElementType* AllocateAndConstruct() {
275 return new (Allocate(sizeof(DerivedElementType))) DerivedElementType;
278 // Take in derived element type and copy construct it at location generated by
279 // Allocate().
280 template <typename DerivedElementType>
281 DerivedElementType* AllocateAndCopyFrom(const DerivedElementType* source) {
282 return new (Allocate(sizeof(DerivedElementType)))
283 DerivedElementType(*source);
286 // Construct a new element on top of an existing one.
287 template <typename DerivedElementType>
288 DerivedElementType* ReplaceExistingElement(Iterator at) {
289 at->~BaseElementType();
290 return new (*at) DerivedElementType();
293 template <typename DerivedElementType>
294 void swap(ListContainer<DerivedElementType>& other) {
295 data_.swap(other.data_);
298 // Appends a new item without copying. The original item will not be
299 // destructed and will be replaced with a new DerivedElementType. The
300 // DerivedElementType does not have to match the moved type as a full block
301 // of memory will be moved (up to MaxSizeForDerivedClass()). A pointer to
302 // the moved element is returned.
303 template <typename DerivedElementType>
304 DerivedElementType* AppendByMoving(DerivedElementType* item) {
305 size_t max_size_for_derived_class = MaxSizeForDerivedClass();
306 void* new_item = Allocate(max_size_for_derived_class);
307 memcpy(new_item, static_cast<void*>(item), max_size_for_derived_class);
308 // Construct a new element in-place so it can be destructed safely.
309 new (item) DerivedElementType;
310 return static_cast<DerivedElementType*>(new_item);
313 using ListContainerBase::size;
314 using ListContainerBase::empty;
315 using ListContainerBase::GetCapacityInBytes;
317 void clear() {
318 for (Iterator i = begin(); i != end(); ++i) {
319 i->~BaseElementType();
321 ListContainerBase::clear();
324 using ListContainerBase::AvailableSizeWithoutAnotherAllocationForTesting;
326 // Iterator classes that can be used to access data.
327 /////////////////////////////////////////////////////////////////
328 class Iterator : public ListContainerBase::Iterator {
329 // This class is only defined to forward iterate through
330 // ListContainerCharAllocator.
331 public:
332 Iterator(ListContainerCharAllocator* container,
333 size_t vector_ind,
334 char* item_iter,
335 size_t index)
336 : ListContainerBase::Iterator(container, vector_ind, item_iter, index) {
338 BaseElementType* operator->() const {
339 return reinterpret_cast<BaseElementType*>(item_iterator);
341 BaseElementType* operator*() const {
342 return reinterpret_cast<BaseElementType*>(item_iterator);
344 Iterator operator++(int unused_post_increment) {
345 Iterator tmp = *this;
346 operator++();
347 return tmp;
349 Iterator& operator++() {
350 Increment();
351 ++index_;
352 return *this;
355 private:
356 explicit Iterator(const ListContainerBase::Iterator& base_iterator)
357 : ListContainerBase::Iterator(base_iterator) {}
358 friend Iterator ListContainer<BaseElementType>::begin();
359 friend Iterator ListContainer<BaseElementType>::end();
360 friend BaseElementType* ListContainer<BaseElementType>::ElementAt(
361 size_t index);
364 class ConstIterator : public ListContainerBase::ConstIterator {
365 // This class is only defined to forward iterate through
366 // ListContainerCharAllocator.
367 public:
368 ConstIterator(ListContainerCharAllocator* container,
369 size_t vector_ind,
370 char* item_iter,
371 size_t index)
372 : ListContainerBase::ConstIterator(container,
373 vector_ind,
374 item_iter,
375 index) {}
376 ConstIterator(const Iterator& other) // NOLINT
377 : ListContainerBase::ConstIterator(other) {}
378 const BaseElementType* operator->() const {
379 return reinterpret_cast<const BaseElementType*>(item_iterator);
381 const BaseElementType* operator*() const {
382 return reinterpret_cast<const BaseElementType*>(item_iterator);
384 ConstIterator operator++(int unused_post_increment) {
385 ConstIterator tmp = *this;
386 operator++();
387 return tmp;
389 ConstIterator& operator++() {
390 Increment();
391 ++index_;
392 return *this;
395 private:
396 explicit ConstIterator(
397 const ListContainerBase::ConstIterator& base_iterator)
398 : ListContainerBase::ConstIterator(base_iterator) {}
399 friend ConstIterator ListContainer<BaseElementType>::cbegin() const;
400 friend ConstIterator ListContainer<BaseElementType>::cend() const;
401 friend const BaseElementType* ListContainer<BaseElementType>::ElementAt(
402 size_t index) const;
405 class ReverseIterator : public ListContainerBase::ReverseIterator {
406 // This class is only defined to reverse iterate through
407 // ListContainerCharAllocator.
408 public:
409 ReverseIterator(ListContainerCharAllocator* container,
410 size_t vector_ind,
411 char* item_iter,
412 size_t index)
413 : ListContainerBase::ReverseIterator(container,
414 vector_ind,
415 item_iter,
416 index) {}
417 BaseElementType* operator->() const {
418 return reinterpret_cast<BaseElementType*>(item_iterator);
420 BaseElementType* operator*() const {
421 return reinterpret_cast<BaseElementType*>(item_iterator);
423 ReverseIterator operator++(int unused_post_increment) {
424 ReverseIterator tmp = *this;
425 operator++();
426 return tmp;
428 ReverseIterator& operator++() {
429 ReverseIncrement();
430 ++index_;
431 return *this;
434 private:
435 explicit ReverseIterator(ListContainerBase::ReverseIterator base_iterator)
436 : ListContainerBase::ReverseIterator(base_iterator) {}
437 friend ReverseIterator ListContainer<BaseElementType>::rbegin();
438 friend ReverseIterator ListContainer<BaseElementType>::rend();
441 class ConstReverseIterator : public ListContainerBase::ConstReverseIterator {
442 // This class is only defined to reverse iterate through
443 // ListContainerCharAllocator.
444 public:
445 ConstReverseIterator(ListContainerCharAllocator* container,
446 size_t vector_ind,
447 char* item_iter,
448 size_t index)
449 : ListContainerBase::ConstReverseIterator(container,
450 vector_ind,
451 item_iter,
452 index) {}
453 ConstReverseIterator(const ReverseIterator& other) // NOLINT
454 : ListContainerBase::ConstReverseIterator(other) {}
455 const BaseElementType* operator->() const {
456 return reinterpret_cast<const BaseElementType*>(item_iterator);
458 const BaseElementType* operator*() const {
459 return reinterpret_cast<const BaseElementType*>(item_iterator);
461 ConstReverseIterator operator++(int unused_post_increment) {
462 ConstReverseIterator tmp = *this;
463 operator++();
464 return tmp;
466 ConstReverseIterator& operator++() {
467 ReverseIncrement();
468 ++index_;
469 return *this;
472 private:
473 explicit ConstReverseIterator(
474 ListContainerBase::ConstReverseIterator base_iterator)
475 : ListContainerBase::ConstReverseIterator(base_iterator) {}
476 friend ConstReverseIterator ListContainer<BaseElementType>::crbegin() const;
477 friend ConstReverseIterator ListContainer<BaseElementType>::crend() const;
481 } // namespace cc
483 #endif // CC_BASE_LIST_CONTAINER_H_