Darwin-Streaming-Server/CommonUtilitiesLib/SVector.h
Darren VanBuren 849723c9cf Add even more of the source
This should be about everything needed to build so far?
2017-03-07 17:14:16 -08:00

227 lines
5.7 KiB
C++

/*
*
* @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 T>
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<EqualOp>(searchStart, searchEnd, target); }
//Allows you to specify an equality comparison functor
template<class Eq>
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<EqualOp>(target); }
template<class Eq>
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<T *>(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_