nestopia/source/core/NstVector.hpp
2012-09-02 13:13:55 -04:00

342 lines
7.6 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////
//
// Nestopia - NES/Famicom emulator written in C++
//
// Copyright (C) 2003-2008 Martin Freij
//
// This file is part of Nestopia.
//
// Nestopia is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// Nestopia is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Nestopia; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////////////
#ifndef NST_VECTOR_H
#define NST_VECTOR_H
#ifndef NST_ASSERT_H
#include "NstAssert.hpp"
#endif
#ifdef NST_PRAGMA_ONCE
#pragma once
#endif
namespace Nes
{
namespace Core
{
template<typename T>
class Vector;
template<>
class Vector<void>
{
public:
static void* Malloc(dword);
static void* Realloc(void*,dword);
static void Free(void*);
static void Copy(void*,const void*,dword);
static void Move(void*,const void*,dword);
template<typename T>
static void Copy(T& dst,const T& src)
{
Copy( &dst, &src, sizeof(T) );
}
};
template<> inline void Vector<void>::Copy(char& dst,const char& src) { dst = src; }
template<> inline void Vector<void>::Copy(schar& dst,const schar& src) { dst = src; }
template<> inline void Vector<void>::Copy(uchar& dst,const uchar& src) { dst = src; }
template<> inline void Vector<void>::Copy(short& dst,const short& src) { dst = src; }
template<> inline void Vector<void>::Copy(ushort& dst,const ushort& src) { dst = src; }
template<> inline void Vector<void>::Copy(int& dst,const int& src) { dst = src; }
template<> inline void Vector<void>::Copy(uint& dst,const uint& src) { dst = src; }
template<> inline void Vector<void>::Copy(long& dst,const long& src) { dst = src; }
template<> inline void Vector<void>::Copy(ulong& dst,const ulong& src) { dst = src; }
template<typename T>
class Vector
{
T* data;
dword size;
dword capacity;
void MakeRoom(dword);
typedef Vector<void> Allocator;
public:
typedef T Type;
Vector();
explicit Vector(dword);
Vector(const Vector<T>&);
Vector(const T*,dword);
bool operator == (const Vector<T>&) const;
void Reserve(dword);
void Resize(dword);
void Expand(dword);
void Assign(const T*,dword);
void Append(const T&);
void Append(const T*,dword);
T* Insert(T*,const T&);
void Erase(T*,dword=1);
void Destroy();
void Defrag();
static void Swap(Vector<T>&,Vector<T>&);
~Vector()
{
Allocator::Free( data );
}
void operator = (const Vector<T>& vector)
{
Assign( vector.data, vector.size );
}
void operator += (const Vector<T>& vector)
{
Append( vector.data, vector.size );
}
T& operator [] (dword i) const
{
NST_ASSERT( i < size );
return data[i];
}
T* Begin() const
{
return data;
}
T* End() const
{
return data + size;
}
dword Size() const
{
return size;
}
dword Capacity() const
{
return capacity;
}
T& Front() const
{
NST_ASSERT( size );
return data[0];
}
T& Back() const
{
NST_ASSERT( size );
return data[size - 1];
}
const T& Pop()
{
NST_ASSERT( size );
return data[--size];
}
void SetTo(dword count)
{
NST_ASSERT( count <= capacity );
size = count;
}
void Clear()
{
size = 0;
}
};
template<typename T>
Vector<T>::Vector()
: data(NULL), size(0), capacity(0) {}
template<typename T>
Vector<T>::Vector(const dword count)
: data(count ? static_cast<T*>(Allocator::Malloc(count * sizeof(T))) : NULL), size(count), capacity(count)
{
}
template<typename T>
Vector<T>::Vector(const T* in,const dword count)
: data(count ? static_cast<T*>(Allocator::Malloc(count * sizeof(T))) : NULL), size(count), capacity(count)
{
Allocator::Copy( data, in, count * sizeof(T) );
}
template<typename T>
Vector<T>::Vector(const Vector<T>& v)
: data(v.size ? static_cast<T*>(Allocator::Malloc(v.size * sizeof(T))) : NULL), size(v.size), capacity(v.size)
{
Allocator::Copy( data, v.data, v.size * sizeof(T) );
}
template<typename T>
void Vector<T>::MakeRoom(const dword count)
{
NST_ASSERT( count );
data = static_cast<T*>(Allocator::Realloc( data, count * sizeof(T) ));
capacity = count;
}
template<typename T>
void Vector<T>::Append(const T& value)
{
if (size == capacity)
MakeRoom( (size + 1) * 2 );
Allocator::Copy( data[size++], value );
}
template<typename T>
void Vector<T>::Assign(const T* const NST_RESTRICT inData,const dword inSize)
{
if (capacity < inSize)
MakeRoom( inSize );
Allocator::Copy( data, inData, (size=inSize) * sizeof(T) );
}
template<typename T>
void Vector<T>::Append(const T* const NST_RESTRICT inData,const dword inSize)
{
if (capacity < size + inSize)
MakeRoom( (size * 2) + inSize );
void* const tmp = data + size;
size += inSize;
Allocator::Copy( tmp, inData, inSize * sizeof(T) );
}
template<typename T>
T* Vector<T>::Insert(T* it,const T& value)
{
const dword pos = it - data;
if (size++ == capacity)
MakeRoom( size * 2 );
Allocator::Move( data+pos+1, data+pos, (size - (pos+1)) * sizeof(T) );
Allocator::Copy( data[pos], value );
return data+pos;
}
template<typename T>
void Vector<T>::Erase(T* it,dword count)
{
NST_ASSERT( size >= count );
const dword s = size;
size -= count;
Allocator::Move( it, it + count, (s - ((it-data) + count)) * sizeof(T) );
}
template<typename T>
void Vector<T>::Reserve(dword count)
{
if (capacity < count)
MakeRoom( count );
}
template<typename T>
void Vector<T>::Resize(dword count)
{
Reserve( count );
size = count;
}
template<typename T>
void Vector<T>::Expand(dword count)
{
Reserve( size + count );
size += count;
}
template<typename T>
void Vector<T>::Defrag()
{
if (size)
{
MakeRoom( size );
}
else if (void* const tmp = data)
{
data = NULL;
capacity = 0;
Allocator::Free( tmp );
}
}
template<typename T>
bool Vector<T>::operator == (const Vector<T>& vector) const
{
if (size != vector.size)
return false;
for (const T *a=data, *b=vector.data, *const end=data+size; a != end; ++a, ++b)
{
if (!(*a == *b))
return false;
}
return true;
}
template<typename T>
void Vector<T>::Destroy()
{
if (void* const tmp = data)
{
data = NULL;
size = 0;
capacity = 0;
Allocator::Free( tmp );
}
}
template<typename T>
void Vector<T>::Swap(Vector<T>& a,Vector<T>& b)
{
T* t = a.data;
a.data = b.data;
b.data = t;
dword u = a.size;
a.size = b.size;
b.size = u;
u = a.capacity;
a.capacity = b.capacity;
b.capacity = u;
}
}
}
#endif