/* PCSX2 - PS2 Emulator for PCs * Copyright (C) 2002-2010 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. * * PCSX2 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 PCSX2. * If not, see . */ #pragma once #include "common/Dependencies.h" // pxUSE_SECURE_MALLOC - enables bounds checking on scoped malloc allocations. #ifndef pxUSE_SECURE_MALLOC #define pxUSE_SECURE_MALLOC 0 #endif // Microsoft Windows only macro, useful for freeing out COM objects: #define safe_release(ptr) \ ((void)((((ptr) != NULL) && ((ptr)->Release(), !!0)), (ptr) = NULL)) // -------------------------------------------------------------------------------------- // SafeArray // -------------------------------------------------------------------------------------- // Handy little class for allocating a resizable memory block, complete with exception // error handling and automatic cleanup. A lightweight alternative to std::vector. // template class SafeArray { DeclareNoncopyableObject(SafeArray); public: static const int DefaultChunkSize = 0x1000 * sizeof(T); public: wxString Name; // user-assigned block name int ChunkSize; protected: T* m_ptr; int m_size; // size of the allocation of memory protected: SafeArray(const wxChar* name, T* allocated_mem, int initSize); virtual T* _virtual_realloc(int newsize); // A safe array index fetcher. Asserts if the index is out of bounds (dev and debug // builds only -- no bounds checking is done in release builds). T* _getPtr(uint i) const; public: virtual ~SafeArray(); explicit SafeArray(const wxChar* name = L"Unnamed"); explicit SafeArray(int initialSize, const wxChar* name = L"Unnamed"); void Dispose(); void ExactAlloc(int newsize); void MakeRoomFor(int newsize) { if (newsize > m_size) ExactAlloc(newsize); } bool IsDisposed() const { return (m_ptr == NULL); } // Returns the size of the memory allocation, as according to the array type. int GetLength() const { return m_size; } // Returns the size of the memory allocation in bytes. int GetSizeInBytes() const { return m_size * sizeof(T); } // Extends the containment area of the array. Extensions are performed // in chunks. void GrowBy(int items) { MakeRoomFor(m_size + ChunkSize + items + 1); } // Gets a pointer to the requested allocation index. // DevBuilds : Generates assertion if the index is invalid. T* GetPtr(uint idx = 0) { return _getPtr(idx); } const T* GetPtr(uint idx = 0) const { return _getPtr(idx); } // Gets a pointer to the element directly after the last element in the array. // This is equivalent to doing GetPtr(GetLength()), except that this call *avoids* // the out-of-bounds assertion check that typically occurs when you do that. :) T* GetPtrEnd() { return &m_ptr[m_size]; } const T* GetPtrEnd() const { return &m_ptr[m_size]; } // Gets an element of this memory allocation much as if it were an array. // DevBuilds : Generates assertion if the index is invalid. T& operator[](int idx) { return *_getPtr((uint)idx); } const T& operator[](int idx) const { return *_getPtr((uint)idx); } virtual SafeArray* Clone() const; }; ////////////////////////////////////////////////////////////////////////////////////////// // SafeList - Simple growable container without all the mess or hassle of std containers. // // This container is intended for reasonably simple class types only. Things which this // container does not handle with desired robustness: // // * Classes with non-trivial constructors (such that construction creates much overhead) // * Classes with copy constructors (copying is done using performance memcpy) // * Classes with destructors (they're not called, sorry!) // template class SafeList { DeclareNoncopyableObject(SafeList); public: static const int DefaultChunkSize = 0x80 * sizeof(T); public: wxString Name; // user-assigned block name int ChunkSize; // assigned DefaultChunkSize on init, reconfigurable at any time. protected: T* m_ptr; int m_allocsize; // size of the allocation of memory uint m_length; // length of the array (active items, not buffer allocation) protected: virtual T* _virtual_realloc(int newsize); void _MakeRoomFor_threshold(int newsize); T* _getPtr(uint i) const; public: virtual ~SafeList(); explicit SafeList(const wxChar* name = L"Unnamed"); explicit SafeList(int initialSize, const wxChar* name = L"Unnamed"); virtual SafeList* Clone() const; void Remove(int index); void MakeRoomFor(int blockSize); T& New(); int Add(const T& src); T& AddNew(const T& src); // Returns the size of the list, as according to the array type. This includes // mapped items only. The actual size of the allocation may differ. int GetLength() const { return m_length; } // Returns the size of the list, in bytes. This includes mapped items only. // The actual size of the allocation may differ. int GetSizeInBytes() const { return m_length * sizeof(T); } void MatchLengthToAllocatedSize() { m_length = m_allocsize; } void GrowBy(int items) { MakeRoomFor(m_length + ChunkSize + items + 1); } // Sets the item length to zero. Does not free memory allocations. void Clear() { m_length = 0; } // Gets an element of this memory allocation much as if it were an array. // DevBuilds : Generates assertion if the index is invalid. T& operator[](int idx) { return *_getPtr((uint)idx); } const T& operator[](int idx) const { return *_getPtr((uint)idx); } T* GetPtr() { return m_ptr; } const T* GetPtr() const { return m_ptr; } T& GetLast() { return m_ptr[m_length - 1]; } const T& GetLast() const { return m_ptr[m_length - 1]; } }; // -------------------------------------------------------------------------------------- // SafeAlignedArray // -------------------------------------------------------------------------------------- // Handy little class for allocating a resizable memory block, complete with // exception-based error handling and automatic cleanup. // This one supports aligned data allocations too! template class SafeAlignedArray : public SafeArray { typedef SafeArray _parent; protected: T* _virtual_realloc(int newsize); public: using _parent::operator[]; virtual ~SafeAlignedArray(); explicit SafeAlignedArray(const wxChar* name = L"Unnamed") : SafeArray::SafeArray(name) { } explicit SafeAlignedArray(int initialSize, const wxChar* name = L"Unnamed"); virtual SafeAlignedArray* Clone() const; };