/ Published in: C++
Expand |
Embed | Plain Text
// file: edmem.h /* * Epic Delusions Multimedia API v0.5b * Cross platform API for games and multimedia applications * * Memory Management Module Revision 1 * * Copyright (c) 1993-2009, Orlando Llanes ([email protected]) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name of the Epic Delusions Development Team nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef edmem_h #define edmem_h #include "eddef.h" /* * Memory allocation object */ class CEDMemBuf { public: CEDMemBuf(); virtual ~CEDMemBuf(); bool Create( edu32 p_size, bool p_clear = true ); void Destroy(); void* KeepBuf(); void* BufPtr( edu32 p_ofs = 0 ); edu32 BufSize( edu32 p_ofs = 0 ); bool Resize( edu32 p_newSize ); bool Grow( edu32 p_newSize, edu32 p_gapOfs = 0, edu32 p_gapSize = 0 ); bool Shrink( edu32 p_newSize, edu32 p_gapOfs = 0, edu32 p_gapSize = 0 ); bool InsertGap( edu32 p_ofs, edu32 p_size, edu32 p_limit = 0 ); bool DeleteGap( edu32 p_ofs, edu32 p_size, edu32 p_limit = 0 ); protected: edu8* m_buf; edu32 m_size; }; void CEDMemBuf_Free( void** p_buf ); #endif // file: edmem.cpp /* * Epic Delusions Multimedia API v0.5b * Cross platform API for games and multimedia applications * * Memory Management Module Revision 1 * * Copyright (c) 1993-2009, Orlando Llanes ([email protected]) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name of the Epic Delusions Development Team nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "edmem.h" #include <stddef.h> #include <string.h> /* * Memory allocation object */ CEDMemBuf::CEDMemBuf(): m_buf(NULL), m_size(0) { } CEDMemBuf::~CEDMemBuf() { Destroy(); } bool CEDMemBuf::Create( edu32 p_size, bool p_clear ) { if( p_size ) { Destroy(); m_buf = new edu8[p_size]; if( m_buf ) { if( p_clear ) memset( m_buf, 0, p_size ); m_size = p_size; return true; } } return false; } void CEDMemBuf::Destroy() { if( m_buf ) delete[] m_buf; m_buf = NULL; m_size = 0; } void* CEDMemBuf::KeepBuf() { edu8* l_buf; if( m_buf ) { l_buf = (edu8*)m_buf; m_buf = NULL; m_size = 0; return l_buf; } return NULL; } void* CEDMemBuf::BufPtr( edu32 p_ofs ) { if( m_buf && (p_ofs < m_size) ) return (((edu8*)m_buf) + p_ofs); return NULL; } edu32 CEDMemBuf::BufSize( edu32 p_ofs ) { if( m_buf && (p_ofs < m_size) ) return (m_size - p_ofs); return 0; } bool CEDMemBuf::Resize( edu32 p_newSize ) { edu32 l_size; edu8* l_buf; if( p_newSize == 0 ) return false; if( p_newSize == m_size ) return (m_buf != NULL); l_buf = new edu8[p_newSize]; if( l_buf == NULL ) return false; l_size = m_size; if( p_newSize < l_size ) l_size = p_newSize; if( m_buf ) { memcpy( l_buf, m_buf, l_size ); delete[] m_buf; } m_buf = l_buf; m_size = p_newSize; return true; } bool CEDMemBuf::Grow( edu32 p_newSize, edu32 p_gapOfs, edu32 p_gapSize ) { edu32 l_gapEnd = p_gapOfs + p_gapSize; edu32 l_size; edu8* l_buf; if( m_buf == NULL ) return Resize(p_newSize); if( p_newSize == m_size ) return InsertGap( p_gapOfs, p_gapSize ); l_buf = new edu8[p_newSize]; if( l_buf == NULL ) return false; if( p_gapOfs < m_size ) { memcpy( l_buf, m_buf, p_gapOfs ); if( (l_gapEnd + (m_size - p_gapOfs)) <= p_newSize ) memcpy( l_buf + p_gapOfs + p_gapSize, m_buf + p_gapOfs, m_size - p_gapOfs ); } else { l_size = m_size; if( p_newSize < l_size ) l_size = p_newSize; memcpy( l_buf, m_buf, l_size ); } delete[] m_buf; m_buf = l_buf; m_size = p_newSize; return true; } bool CEDMemBuf::Shrink( edu32 p_newSize, edu32 p_gapOfs, edu32 p_gapSize ) { edu32 l_gapEnd = p_gapOfs + p_gapSize; edu8* l_buf; if( !(m_buf && p_gapSize) ) return Resize(p_newSize); if( p_gapOfs >= p_newSize ) return (p_gapOfs == p_newSize); if( p_newSize >= m_size ) return (p_newSize == m_size); if( l_gapEnd > m_size ) return false; l_buf = new edu8[p_newSize]; if( l_buf == NULL ) return false; memcpy( l_buf, m_buf, p_gapOfs ); memcpy( l_buf + p_gapOfs, m_buf + l_gapEnd, p_newSize - p_gapOfs ); delete[] m_buf; m_buf = l_buf; m_size = p_newSize; return true; } bool CEDMemBuf::InsertGap( edu32 p_ofs, edu32 p_size, edu32 p_limit ) { edu32 l_tmp = p_ofs + p_size; if( (l_tmp > m_size) || (p_limit > m_size) ) return false; if( p_limit == 0 ) p_limit = m_size; if( m_buf ) { memmove( m_buf + l_tmp, m_buf + p_ofs, p_limit - l_tmp ); return true; } return false; } bool CEDMemBuf::DeleteGap( edu32 p_ofs, edu32 p_size, edu32 p_limit ) { edu32 l_end = p_ofs + p_size; if( !(m_buf && p_size) ) return false; if( p_limit == 0 ) p_limit = m_size; if( p_limit > m_size ) return false; if( p_ofs >= p_limit ) return (p_ofs == p_limit); memmove( m_buf + p_ofs, m_buf + l_end, p_limit - p_ofs ); return true; } // file: edlist.h /* * Epic Delusions Multimedia API v0.5b * Cross platform API for games and multimedia applications * * List Module Revision 4 * * Copyright (c) 1993-2009, Orlando Llanes ([email protected]) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name of the Epic Delusions Development Team nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef edlist_h #define edlist_h #include "eddef.h" #include "edmem.h" template<typename editem_t, typename edkey_t> class CEDKeyList { public: CEDKeyList(); virtual ~CEDKeyList(); virtual bool Create( edu32 p_nItems = 0 ); virtual void Destroy(); virtual bool Sort(); edu32 ItemCount(); bool RemoveItem( edu32 p_index ); bool Remove( const edkey_t p_key ); protected: edu32 FindItem( const edkey_t p_key ); virtual bool GetItem( edu32 p_index, editem_t& p_item ); virtual bool SetItem( edu32 p_index, editem_t& p_item ); bool InsertItem( edu32 p_index, const editem_t& p_item ); bool FreeItem( edu32 p_index ); bool AddItem( const editem_t& p_item ); virtual int CompareKey( const editem_t& p_item, const edkey_t p_key ); virtual int CompareItem( const editem_t& p_left, const editem_t& p_right ); bool SwapItem( edu32 p_indexa, edu32 p_indexb ); protected: CEDMemBuf m_listbuf; editem_t* m_list; edu32 m_nItems; edu32 m_nMax; edu32 m_growBy; }; template<typename editem_t, typename edkey_t> CEDKeyList<editem_t, edkey_t>::CEDKeyList(): m_list(0), m_nItems(0), m_nMax(0), m_growBy(2 << 4) // Set default growth rate to 4 items { } template<typename editem_t, typename edkey_t> CEDKeyList<editem_t, edkey_t>::~CEDKeyList() { Destroy(); } template<typename editem_t, typename edkey_t> bool CEDKeyList<editem_t, edkey_t>::Create( edu32 p_nItems ) { Destroy(); if( p_nItems == 0 ) p_nItems = 1; if( !m_listbuf.Create(p_nItems * sizeof(editem_t)) ) return false; m_list = (editem_t*)m_listbuf.BufPtr(); if( m_list ) { m_nItems = 0; m_nMax = p_nItems; return true; } Destroy(); return false; } template<typename editem_t, typename edkey_t> void CEDKeyList<editem_t, edkey_t>::Destroy() { m_listbuf.Destroy(); m_list = NULL; m_nItems = 0; m_nMax = 0; m_growBy = 2 << 4; // Set default growth rate to 4 items } template<typename editem_t, typename edkey_t> bool CEDKeyList<editem_t, edkey_t>::Sort() { return false; } template<typename editem_t, typename edkey_t> edu32 CEDKeyList<editem_t, edkey_t>::ItemCount() { if( m_list && (m_nItems < m_nMax) ) return m_nItems; return 0; } template<typename editem_t, typename edkey_t> bool CEDKeyList<editem_t, edkey_t>::RemoveItem( edu32 p_index ) { edu32 l_nMax; if( !(m_list && m_nItems) ) return false; if( m_nItems > m_nMax ) return false; if( !FreeItem(p_index) ) return false; if( (m_growBy >> 4) != (m_nMax - m_nItems - 1) ) { if( !m_listbuf.DeleteGap(p_index * sizeof(editem_t), sizeof(editem_t), m_nItems * sizeof(editem_t)) ) return false; m_nItems--; return true; } l_nMax = m_nMax - ((edu32)1 << (m_growBy >> 4)); if( !m_listbuf.Shrink(l_nMax * sizeof(editem_t), p_index * sizeof(editem_t), sizeof(editem_t))) return false; m_list = (testitem_t*)m_listbuf.BufPtr(); if( m_list == NULL ) return false; m_nMax = l_nMax; m_nItems--; if( m_growBy & 15 ) m_growBy--; return true; } template<typename editem_t, typename edkey_t> bool CEDKeyList<editem_t, edkey_t>::Remove( const edkey_t p_key ) { edu32 l_index; l_index = FindItem(p_key); if( l_index != ED_INVALID ) return RemoveItem(l_index); return false; } template<typename editem_t, typename edkey_t> edu32 CEDKeyList<editem_t, edkey_t>::FindItem( const edkey_t p_key ) { edu32 l_left = 0; edu32 l_mid = m_nItems >> 1; edu32 l_right = m_nItems; int l_code; if( !(m_list && m_nItems) ) return ED_INVALID; while( l_left < l_right ) { l_code = CompareKey(m_list[l_mid], p_key); if( l_code == 0 ) return l_mid; if( l_code < 0 ) l_left = l_mid + 1; else l_right = l_mid; l_mid = (l_left + l_right) >> 1; } return ED_INVALID; } template<typename editem_t, typename edkey_t> bool CEDKeyList<editem_t, edkey_t>::GetItem( edu32 p_index, editem_t& p_item ) { if( (p_index >= m_nItems) || (&p_item == NULL) ) return false; p_item = m_list[p_index]; return true; } template<typename editem_t, typename edkey_t> bool CEDKeyList<editem_t, edkey_t>::SetItem( edu32 p_index, editem_t& p_item ) { if( (p_index >= m_nItems) || (&p_item == NULL) ) return false; m_list[p_index] = p_item; return true; } template<typename editem_t, typename edkey_t> bool CEDKeyList<editem_t, edkey_t>::InsertItem( edu32 p_index, const editem_t& p_item ) { edu32 l_nMax; if( !(m_list && (&p_item)) ) return false; if( p_index > m_nMax ) return false; if( m_nItems < m_nMax ) { if( !m_listbuf.InsertGap(p_index * sizeof(editem_t), sizeof(editem_t), (m_nItems + 1) * sizeof(editem_t)) ) return false; m_list[p_index] = p_item; m_nItems++; return true; } l_nMax = m_nMax + ((edu32)1 << (m_growBy >> 4)); // Check for integer overflow if( l_nMax < m_nMax ) return false; // Limit growth rate to 1 << 8 [256] if( m_growBy < ((edu32)8 << 4) ) { m_growBy++; if( (m_growBy & 15) == 15 ) m_growBy = (m_growBy & (~15)) << 1; } if( !m_listbuf.Grow(l_nMax * sizeof(editem_t), p_index * sizeof(editem_t), sizeof(editem_t)) ) return false; m_list = (editem_t*)m_listbuf.BufPtr(); if( m_list == NULL ) return false; m_nMax = l_nMax; m_list[p_index] = p_item; m_nItems++; return true; } template<typename editem_t, typename edkey_t> bool CEDKeyList<editem_t, edkey_t>::FreeItem( edu32 p_index ) { return true; } template<typename editem_t, typename edkey_t> bool CEDKeyList<editem_t, edkey_t>::AddItem( const editem_t& p_item ) { edu32 l_left; edu32 l_mid = 0; edu32 l_right; int l_code; if( m_list == NULL ) return false; if( m_nItems == 0 ) { m_list[0] = p_item; m_nItems++; return true; } // Special case last item, no duplicates allowed l_code = CompareItem(m_list[m_nItems - 1], p_item); if( l_code == 0 ) return false; // If insert position is at end, skip search if( l_code < 0 ) { l_mid = m_nItems; goto Add_SkipSearch; } l_left = 0; l_right = m_nItems; l_mid = (l_left + l_right) >> 1; while( l_left < l_right ) { // No duplicates allowed l_code = CompareItem(m_list[l_mid], p_item); if( l_code == 0 ) return false; if( l_code < 0 ) l_left = l_mid + 1; else l_right = l_mid; l_mid = (l_left + l_right) >> 1; } Add_SkipSearch: return InsertItem(l_mid, p_item); } template<typename editem_t, typename edkey_t> int CEDKeyList<editem_t, edkey_t>::CompareKey( const editem_t& p_item, const edkey_t p_key ) { return 0; } template<typename editem_t, typename edkey_t> int CEDKeyList<editem_t, edkey_t>::CompareItem( const editem_t& p_left, const editem_t& p_right ) { return 0; } template<typename editem_t, typename edkey_t> bool CEDKeyList<editem_t, edkey_t>::SwapItem( edu32 p_indexa, edu32 p_indexb ) { editem_t l_tmp; if( m_list == NULL ) return false; if( (p_indexa > m_nItems) || (p_indexb > m_nItems) ) return false; l_tmp = m_list[p_indexa]; m_list[p_indexa] = m_list[p_indexb]; m_list[p_indexb] = l_tmp; return true; } #endif
Comments
Subscribe to comments
You need to login to post a comment.

CEDMemBuf is a general memory allocator which intends to simplify management of dynamic data. Shrink, Grow, InsertGap and DeleteGap are made to work with list classes based on arrays.
CEDKeyList is a template class for sorted data, based on a dynamic array which grows as needed. Every 16th growth, the growth rate doubles until it hits 256. Insertions are sorted using a modified Binary Search algorithm.
By default, CEDKeyList does not allow duplicates. Duplicates work by deriving a CompareItem function which does not return 0. Note that CompareKey must return 0 on a match.