/* Vector.h Written by Matthew Fisher Template vector library. Extends functionality of std::vector */ #pragma once #include "Asserts.h" // // Intellisense for custom types // //http://thejefffiles.com/blog/autoexpdat-your-key-to-better-debugging-part-1/ #pragma warning(disable : 4700) template class Vector { public: Vector() { _Data = NULL; _Length = 0; _Capacity = 0; } explicit Vector(unsigned int Size) { _Data = new T[Size]; _Length = Size; _Capacity = Size; } Vector(unsigned int Size, const T &ClearValue) { _Data = new T[Size]; _Length = Size; _Capacity = Size; Clear(ClearValue); } Vector(const Vector &V) { const unsigned int Length = V._Length; _Length = Length; _Capacity = Length; if(Length == 0) { _Data = NULL; } else { _Data = new T[Length]; for(unsigned int Index = 0; Index < Length; Index++) { _Data[Index] = V._Data[Index]; } } } ~Vector() { if(_Data != NULL) { delete[] _Data; } } // // Memory // void FreeMemory() { if(_Data != NULL) { delete[] _Data; _Data = NULL; } _Length = 0; _Capacity = 0; } void DeleteMemory() { if(_Data != NULL) { for(UINT Index = 0; Index < _Length; Index++) { delete _Data[Index]; } delete[] _Data; _Data = NULL; } _Length = 0; _Capacity = 0; } // // Windows has claimed the nice name "ZeroMemory" for its own uses // void ZeroMem() { if(_Length > 0) { memset(_Data, 0, _Length * sizeof(T)); } } void operator = (const Vector &V) { const unsigned int Length = V._Length; _Length = Length; _Capacity = Length; if(_Data != NULL) { delete[] _Data; } if(Length == 0) { _Data = NULL; } else { _Data = new T[Length]; for(unsigned int Index = 0; Index < Length; Index++) { _Data[Index] = V._Data[Index]; } } } void Allocate(unsigned int Size) { if(Size == 0) { FreeMemory(); } /*else if(_Length == Size) { if(typeid(T) != typeid(int) && typeid(T) != typeid(unsigned int) && typeid(T) != typeid(double) && typeid(T) != typeid(float) && typeid(T) != typeid(char) && typeid(T) != typeid(unsigned char)) { T Value; for(unsigned int Index = 0; Index < Size; Index++) { _Data[Index] = Value; } } }*/ else { if(_Data != NULL) { delete[] _Data; } _Data = new T[Size]; _Length = Size; _Capacity = Size; } } void Allocate(unsigned int Size, const T &ClearValue) { Allocate(Size); Clear(ClearValue); } void ReSize(unsigned int Size) { if(Size == 0) { FreeMemory(); } else if(Size <= _Capacity) { _Length = Size; if(Size == 0) { if(_Data != NULL) { delete[] _Data; _Capacity = 0; } } } else { unsigned int NewCapacity = Size * 3 / 2 + 4; T *NewData = new T[NewCapacity]; const unsigned int Length = _Length; for(unsigned int Index = 0; Index < Length; Index++) { NewData[Index] = _Data[Index]; } if(_Data) { delete[] _Data; } _Data = NewData; _Length = Size; _Capacity = NewCapacity; } } void Reserve(unsigned int Size) { if(Size > _Capacity) { T *NewData = new T[Size]; if(_Data != NULL) { memcpy(NewData, _Data, sizeof(T) * _Length); for(UINT index = 0; index < _Length; index++) { new (_Data + index) T; } delete[] _Data; } _Data = NewData; _Capacity = Size; } } // // Accessors // __forceinline T& operator [] (unsigned int k) { #ifdef VECTOR_DEBUG if(k >= _Length) { SignalError("Out-of-bounds vector access"); } #endif return _Data[k]; } __forceinline T& operator [] (int k) { #ifdef VECTOR_DEBUG if(k < 0 || k >= int(_Length)) { SignalError("Out-of-bounds vector access"); } #endif return _Data[k]; } __forceinline const T& operator [] (unsigned int k) const { #ifdef VECTOR_DEBUG if(k >= _Length) { SignalError("Out-of-bounds vector access"); } #endif return _Data[k]; } __forceinline const T& operator [] (int k) const { #ifdef VECTOR_DEBUG if(k < 0 || k >= int(_Length)) { SignalError("Out-of-bounds vector access"); } #endif return _Data[k]; } __forceinline unsigned int Length() const { return _Length; } __forceinline T* CArray() { #ifdef VECTOR_DEBUG if(_Length == 0) { SignalError("CArray called on zero-length vector"); } #endif return _Data; } __forceinline const T* CArray() const { #ifdef VECTOR_DEBUG if(_Length == 0) { SignalError("CArray called on zero-length vector"); } #endif return _Data; } __forceinline T& RandomElement() { Assert(_Length > 0, "RandomElement called with no elements"); return _Data[rand() % _Length]; } __forceinline const T& RandomElement() const { Assert(_Length > 0, "RandomElement called with no elements"); return _Data[rand() % _Length]; } __forceinline T& Last() { Assert(_Length > 0, "Last called with no elements"); return _Data[_Length - 1]; } __forceinline const T& Last() const { Assert(_Length > 0, "Last called with no elements"); return _Data[_Length - 1]; } __forceinline T& First() { Assert(_Length > 0, "First called with no elements"); return _Data[0]; } __forceinline const T& First() const { Assert(_Length > 0, "First called with no elements"); return _Data[0]; } __forceinline T* Begin() { return _Data; } __forceinline const T* Begin() const { return _Data; } __forceinline T* End() { return _Data + _Length; } __forceinline const T* End() const { return _Data + _Length; } // // Modifiers // void Append(const Vector &V); void PushEnd(const T &t); void PushEnd(); void PopEnd(); void PopFront(); void RemoveSlow(unsigned int Index); void RemoveSwap(unsigned int Index); void Randomize(); void Sort(); void Scale(const T &t); template void Sort(orderingType Function) { if(_Length >= 2) { std::sort(_Data, _Data + _Length, Function); } } void Clear(const T &T); // // Query // T Sum() const; const T& MaxValue() const; unsigned int MaxIndex() const; const T& MinValue() const; unsigned int MinIndex() const; bool Contains(const T &t) const; int FindFirstIndex(const T &t) const; unsigned int Hash32() const; unsigned __int64 Hash64() const; // // File // void SaveToASCIIFile(const String &Filename) { ofstream File(Filename.CString()); PersistentAssert(!File.fail(), "Failed to open file"); File << _Length << endl; for(unsigned int Index = 0; Index < _Length; Index++) { File << _Data[Index] << '\n'; } } void LoadFromASCIIFile(const String &Filename) { ifstream File(Filename.CString()); PersistentAssert(!File.fail(), "Failed to open file"); unsigned int Length; File >> Length; Allocate(Length); for(unsigned int Index = 0; Index < Length; Index++) { File >> _Data[Index]; } } protected: //vector Data; T *_Data; unsigned int _Length; unsigned int _Capacity; }; #pragma warning(default : 4700) #include "Vector.cpp"