// 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<typename T, class P> void List<T, P>::Add(const T& element) { if (length_ < capacity_) { data_[length_++] = element; } else { List<T, P>::ResizeAdd(element); } } template<typename T, class P> void List<T, P>::AddAll(const List<T, P>& other) { AddAll(other.ToVector()); } template<typename T, class P> void List<T, P>::AddAll(const Vector<T>& 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<typename T, class P> void List<T, P>::ResizeAdd(const T& element) { ResizeAddInternal(element); } template<typename T, class P> void List<T, P>::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<typename T, class P> void List<T, P>::Resize(int new_capacity) { T* new_data = List<T, P>::NewData(new_capacity); memcpy(new_data, data_, capacity_ * sizeof(T)); List<T, P>::DeleteData(data_); data_ = new_data; capacity_ = new_capacity; } template<typename T, class P> Vector<T> List<T, P>::AddBlock(T value, int count) { int start = length_; for (int i = 0; i < count; i++) Add(value); return Vector<T>(&data_[start], count); } template<typename T, class P> void List<T, P>::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<typename T, class P> T List<T, P>::Remove(int i) { T element = at(i); length_--; while (i < length_) { data_[i] = data_[i + 1]; i++; } return element; } template<typename T, class P> bool List<T, P>::RemoveElement(const T& elm) { for (int i = 0; i < length_; i++) { if (data_[i] == elm) { Remove(i); return true; } } return false; } template<typename T, class P> void List<T, P>::Clear() { DeleteData(data_); Initialize(0); } template<typename T, class P> void List<T, P>::Rewind(int pos) { length_ = pos; } template<typename T, class P> void List<T, P>::Iterate(void (*callback)(T* x)) { for (int i = 0; i < length_; i++) callback(&data_[i]); } template<typename T, class P> template<class Visitor> void List<T, P>::Iterate(Visitor* visitor) { for (int i = 0; i < length_; i++) visitor->Apply(&data_[i]); } template<typename T, class P> bool List<T, P>::Contains(const T& elm) const { for (int i = 0; i < length_; i++) { if (data_[i] == elm) return true; } return false; } template<typename T, class P> int List<T, P>::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<typename T, class P> void List<T, P>::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<typename T, class P> void List<T, P>::Sort() { Sort(PointerValueCompare<T>); } template<typename T, class P> void List<T, P>::Initialize(int capacity) { ASSERT(capacity >= 0); data_ = (capacity > 0) ? NewData(capacity) : NULL; capacity_ = capacity; length_ = 0; } template <typename T> int SortedListBSearch( const List<T>& list, T elem, int (*cmp)(const T* x, const T* y)) { 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, &elem) > 0) { high = mid - 1; continue; } if (cmp(&mid_elem, &elem) < 0) { low = mid + 1; continue; } // Found the elememt. return mid; } return -1; } template <typename T> int SortedListBSearch(const List<T>& list, T elem) { return SortedListBSearch<T>(list, elem, PointerValueCompare<T>); } } } // namespace v8::internal #endif // V8_LIST_INL_H_