// Copyright 2006-2009 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_LIST_INL_H_ #define V8_LIST_INL_H_ #include "src/list.h" #include "src/base/macros.h" #include "src/base/platform/platform.h" namespace v8 { namespace internal { template void List::Add(const T& element, P alloc) { if (length_ < capacity_) { data_[length_++] = element; } else { List::ResizeAdd(element, alloc); } } template void List::AddAll(const List& other, P alloc) { AddAll(other.ToVector(), alloc); } template void List::AddAll(const Vector& other, P alloc) { int result_length = length_ + other.length(); if (capacity_ < result_length) Resize(result_length, alloc); if (base::is_fundamental()) { memcpy(data_ + length_, other.start(), sizeof(*data_) * other.length()); } else { for (int i = 0; i < other.length(); i++) data_[length_ + i] = other.at(i); } length_ = result_length; } // Use two layers of inlining so that the non-inlined function can // use the same implementation as the inlined version. template void List::ResizeAdd(const T& element, P alloc) { ResizeAddInternal(element, alloc); } template void List::ResizeAddInternal(const T& element, P alloc) { DCHECK(length_ >= capacity_); // Grow the list capacity by 100%, but make sure to let it grow // even when the capacity is zero (possible initial case). int new_capacity = 1 + 2 * capacity_; // Since the element reference could be an element of the list, copy // it out of the old backing storage before resizing. T temp = element; Resize(new_capacity, alloc); data_[length_++] = temp; } template void List::Resize(int new_capacity, P alloc) { DCHECK_LE(length_, new_capacity); T* new_data = NewData(new_capacity, alloc); MemCopy(new_data, data_, length_ * sizeof(T)); List::DeleteData(data_); data_ = new_data; capacity_ = new_capacity; } template Vector List::AddBlock(T value, int count, P alloc) { int start = length_; for (int i = 0; i < count; i++) Add(value, alloc); return Vector(&data_[start], count); } template void List::Set(int index, const T& elm) { DCHECK(index >= 0 && index <= length_); data_[index] = elm; } template void List::InsertAt(int index, const T& elm, P alloc) { DCHECK(index >= 0 && index <= length_); Add(elm, alloc); for (int i = length_ - 1; i > index; --i) { data_[i] = data_[i - 1]; } data_[index] = elm; } template T List::Remove(int i) { T element = at(i); length_--; while (i < length_) { data_[i] = data_[i + 1]; i++; } return element; } template bool List::RemoveElement(const T& elm) { for (int i = 0; i < length_; i++) { if (data_[i] == elm) { Remove(i); return true; } } return false; } template void List::Allocate(int length, P allocator) { DeleteData(data_); Initialize(length, allocator); length_ = length; } template void List::Clear() { DeleteData(data_); // We don't call Initialize(0) since that requires passing a Zone, // which we don't really need. data_ = NULL; capacity_ = 0; length_ = 0; } template void List::Rewind(int pos) { DCHECK(0 <= pos && pos <= length_); length_ = pos; } template void List::Trim(P alloc) { if (length_ < capacity_ / 4) { Resize(capacity_ / 2, alloc); } } template void List::Iterate(void (*callback)(T* x)) { for (int i = 0; i < length_; i++) callback(&data_[i]); } template template void List::Iterate(Visitor* visitor) { for (int i = 0; i < length_; i++) visitor->Apply(&data_[i]); } template bool List::Contains(const T& elm) const { for (int i = 0; i < length_; i++) { if (data_[i] == elm) return true; } return false; } template int List::CountOccurrences(const T& elm, int start, int end) const { int result = 0; for (int i = start; i <= end; i++) { if (data_[i] == elm) ++result; } return result; } template void List::Sort(int (*cmp)(const T* x, const T* y)) { ToVector().Sort(cmp); #ifdef DEBUG for (int i = 1; i < length_; i++) DCHECK(cmp(&data_[i - 1], &data_[i]) <= 0); #endif } template void List::Sort() { ToVector().Sort(); } template void List::Initialize(int capacity, P allocator) { DCHECK(capacity >= 0); data_ = (capacity > 0) ? NewData(capacity, allocator) : NULL; capacity_ = capacity; length_ = 0; } template int SortedListBSearch(const List& list, P cmp) { int low = 0; int high = list.length() - 1; while (low <= high) { int mid = (low + high) / 2; T mid_elem = list[mid]; if (cmp(&mid_elem) > 0) { high = mid - 1; continue; } if (cmp(&mid_elem) < 0) { low = mid + 1; continue; } // Found the elememt. return mid; } return -1; } template class ElementCmp { public: explicit ElementCmp(T e) : elem_(e) {} int operator()(const T* other) { return PointerValueCompare(other, &elem_); } private: T elem_; }; template int SortedListBSearch(const List& list, T elem) { return SortedListBSearch > (list, ElementCmp(elem)); } } } // namespace v8::internal #endif // V8_LIST_INL_H_