/* * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2008 Apple Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ * */ /* * SVector.h * * An simple, non-exception safe implementation of vector */ #ifndef _SVECTOR_H_ #define _SVECTOR_H_ #include"OSHeaders.h" #include"OSMemory.h" //T must be default and copy constructable; does not have to be assignable template class SVector { public: explicit SVector(UInt32 newCapacity = 0) : fCapacity(0), fSize(0), fData(NULL) { reserve(newCapacity); } SVector(const SVector &rhs) : fCapacity(0), fSize(0), fData(NULL) { reserve(rhs.size()); fSize = rhs.size(); for(UInt32 i = 0; i < rhs.size(); ++i) NEW(fData + i) T(rhs[i]); } ~SVector() { clear(); operator delete[](fData); } SVector &operator=(const SVector &rhs) { clear(); reserve(rhs.size()); fSize = rhs.size(); for(UInt32 i = 0; i < rhs.size(); ++i) NEW(fData + i) T(rhs[i]); return *this; } T &operator[](UInt32 i) const { return fData[i]; } T &front() const { return fData[0]; } T &back() const { return fData[fSize - 1]; } T *begin() const { return fData; } T *end() const { return fData + fSize; } //Returns searchEnd if target is not found; uses == for equality comparison UInt32 find(UInt32 searchStart, UInt32 searchEnd, const T &target) { return find(searchStart, searchEnd, target); } //Allows you to specify an equality comparison functor template UInt32 find(UInt32 searchStart, UInt32 searchEnd, const T &target, Eq eq = Eq()) { UInt32 i = searchStart; for(; i < searchEnd; ++i) if (eq(target, fData[i])) break; return i; } //returns size() if the element is not found UInt32 find(const T &target) { return find(target); } template UInt32 find(const T &target, Eq eq = Eq()) { return find(0, size(), target, eq); } //Doubles the capacity as needed void push_back(const T &newItem) { reserve(fSize + 1); NEW (fData + fSize) T(newItem); fSize++; } void pop_back() { fData[--fSize].~T(); } void swap(SVector &rhs) { UInt32 tmpCapacity = fCapacity; UInt32 tmpSize = fSize; T *tmpData = fData; fCapacity = rhs.fCapacity; fSize = rhs.fSize; fData = rhs.fData; rhs.fCapacity = tmpCapacity; rhs.fSize = tmpSize; rhs.fData = tmpData; } void insert(UInt32 position, const T &newItem) { insert(position, 1, newItem); } void insert(UInt32 position, UInt32 count, const T &newItem) { reserve(fSize + count); for(UInt32 i = fSize; i > position; --i) { NEW (fData + i - 1 + count) T(fData[i - 1]); fData[i - 1].~T(); } for(UInt32 i = position; i < position + count; ++i) NEW (fData + i) T(newItem); fSize += count; } //can accept count of 0 - which results in a NOP void erase(UInt32 position, UInt32 count = 1) { if(count == 0) return; for(UInt32 i = position; i < position + count; ++i) fData[i].~T(); for(UInt32 i = position + count; i < fSize; ++i) { NEW (fData + i - count) T(fData[i]); fData[i].~T(); } fSize -= count; } //Removes 1 element by swapping it with the last item. void swap_erase(UInt32 position) { fData[position].~T(); if (position < --fSize) { NEW(fData + position) T(fData[fSize]); fData[fSize].~T(); } } Bool16 empty() const { return fSize == 0; } UInt32 capacity() const { return fCapacity; } UInt32 size() const { return fSize; } void clear() { resize(0); } //unlike clear(), this will free the memories void wipe() { this->~SVector(); fCapacity = fSize = 0; fData = NULL; } //Doubles the capacity on a reallocation to preserve linear time semantics void reserve(UInt32 newCapacity) { if (newCapacity > fCapacity) { UInt32 targetCapacity = fCapacity == 0 ? 4 : fCapacity; while(targetCapacity < newCapacity) targetCapacity *= 2; reserveImpl(targetCapacity); } } void resize(UInt32 newSize, const T &newItem = T()) { if (newSize > fSize) { reserve(newSize); for(UInt32 i = fSize; i < newSize; ++i) NEW(fData + i) T(newItem); } else if (newSize < fSize) { for(UInt32 i = newSize; i < fSize; ++i) fData[i].~T(); } fSize = newSize; } private: void reserveImpl(UInt32 newCapacity) { T *newData = static_cast(operator new[](sizeof(T) * newCapacity)); fCapacity = newCapacity; for(UInt32 i = 0; i < fSize; ++i) NEW (newData + i) T(fData[i]); operator delete[](fData); fData = newData; } UInt32 fCapacity; UInt32 fSize; T *fData; struct EqualOp { bool operator()(const T &left, const T &right) { return left == right; } }; }; #endif //_SVECTOR_H_