// Copyright 2006-2009 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef V8_LIST_INL_H_ #define V8_LIST_INL_H_ #include "list.h" namespace v8 { namespace internal { template void List::Add(const T& element) { if (length_ < capacity_) { data_[length_++] = element; } else { List::ResizeAdd(element); } } template void List::AddAll(const List& other) { AddAll(other.ToVector()); } template void List::AddAll(const Vector& other) { int result_length = length_ + other.length(); if (capacity_ < result_length) Resize(result_length); 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) { ResizeAddInternal(element); } template void List::ResizeAddInternal(const T& element) { ASSERT(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); data_[length_++] = temp; } template void List::Resize(int new_capacity) { T* new_data = List::NewData(new_capacity); memcpy(new_data, data_, capacity_ * sizeof(T)); List::DeleteData(data_); data_ = new_data; capacity_ = new_capacity; } template Vector List::AddBlock(T value, int count) { int start = length_; for (int i = 0; i < count; i++) Add(value); return Vector(&data_[start], count); } template void List::InsertAt(int index, const T& elm) { ASSERT(index >= 0 && index <= length_); Add(elm); 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) { DeleteData(data_); Initialize(length); length_ = length; } template void List::Clear() { DeleteData(data_); Initialize(0); } template void List::Rewind(int pos) { length_ = pos; } 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++) ASSERT(cmp(&data_[i - 1], &data_[i]) <= 0); #endif } template void List::Sort() { Sort(PointerValueCompare); } template void List::Initialize(int capacity) { ASSERT(capacity >= 0); data_ = (capacity > 0) ? NewData(capacity) : 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_