2017-08-01 14:30:58 +02:00
|
|
|
#ifndef GIM_ARRAY_H_INCLUDED
|
|
|
|
#define GIM_ARRAY_H_INCLUDED
|
|
|
|
/*! \file gim_array.h
|
|
|
|
\author Francisco Leon Najera
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
This source file is part of GIMPACT Library.
|
|
|
|
|
|
|
|
For the latest info, see http://gimpact.sourceforge.net/
|
|
|
|
|
|
|
|
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
|
|
|
|
email: projectileman@yahoo.com
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of EITHER:
|
|
|
|
(1) The GNU Lesser General Public License as published by the Free
|
|
|
|
Software Foundation; either version 2.1 of the License, or (at
|
|
|
|
your option) any later version. The text of the GNU Lesser
|
|
|
|
General Public License is included with this library in the
|
|
|
|
file GIMPACT-LICENSE-LGPL.TXT.
|
|
|
|
(2) The BSD-style license that is included with this library in
|
|
|
|
the file GIMPACT-LICENSE-BSD.TXT.
|
|
|
|
(3) The zlib/libpng license that is included with this library in
|
|
|
|
the file GIMPACT-LICENSE-ZLIB.TXT.
|
|
|
|
|
|
|
|
This library 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 files
|
|
|
|
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
|
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gim_memory.h"
|
|
|
|
|
|
|
|
#define GIM_ARRAY_GROW_INCREMENT 2
|
|
|
|
#define GIM_ARRAY_GROW_FACTOR 2
|
|
|
|
|
|
|
|
//! Very simple array container with fast access and simd memory
|
2019-01-03 14:26:51 +01:00
|
|
|
template <typename T>
|
2017-08-01 14:30:58 +02:00
|
|
|
class gim_array
|
|
|
|
{
|
|
|
|
public:
|
2019-01-03 14:26:51 +01:00
|
|
|
//! properties
|
|
|
|
//!@{
|
|
|
|
T* m_data;
|
|
|
|
GUINT m_size;
|
|
|
|
GUINT m_allocated_size;
|
|
|
|
//!@}
|
|
|
|
//! protected operations
|
|
|
|
//!@{
|
|
|
|
|
|
|
|
inline void destroyData()
|
|
|
|
{
|
|
|
|
m_allocated_size = 0;
|
|
|
|
if (m_data == NULL) return;
|
2017-08-01 14:30:58 +02:00
|
|
|
gim_free(m_data);
|
|
|
|
m_data = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool resizeData(GUINT newsize)
|
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
if (newsize == 0)
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
|
|
|
destroyData();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
if (m_size > 0)
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
m_data = (T*)gim_realloc(m_data, m_size * sizeof(T), newsize * sizeof(T));
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
m_data = (T*)gim_alloc(newsize * sizeof(T));
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
m_allocated_size = newsize;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool growingCheck()
|
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
if (m_allocated_size <= m_size)
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
GUINT requestsize = m_size;
|
|
|
|
m_size = m_allocated_size;
|
|
|
|
if (resizeData((requestsize + GIM_ARRAY_GROW_INCREMENT) * GIM_ARRAY_GROW_FACTOR) == false) return false;
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
//!@}
|
|
|
|
//! public operations
|
|
|
|
//!@{
|
|
|
|
inline bool reserve(GUINT size)
|
|
|
|
{
|
|
|
|
if (m_allocated_size >= size) return false;
|
|
|
|
return resizeData(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void clear_range(GUINT start_range)
|
|
|
|
{
|
|
|
|
while (m_size > start_range)
|
|
|
|
{
|
|
|
|
m_data[--m_size].~T();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void clear()
|
|
|
|
{
|
|
|
|
if (m_size == 0) return;
|
|
|
|
clear_range(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void clear_memory()
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
destroyData();
|
|
|
|
}
|
|
|
|
|
|
|
|
gim_array()
|
|
|
|
{
|
|
|
|
m_data = 0;
|
|
|
|
m_size = 0;
|
|
|
|
m_allocated_size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
gim_array(GUINT reservesize)
|
|
|
|
{
|
|
|
|
m_data = 0;
|
|
|
|
m_size = 0;
|
|
|
|
|
|
|
|
m_allocated_size = 0;
|
|
|
|
reserve(reservesize);
|
|
|
|
}
|
|
|
|
|
|
|
|
~gim_array()
|
|
|
|
{
|
|
|
|
clear_memory();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline GUINT size() const
|
|
|
|
{
|
|
|
|
return m_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline GUINT max_size() const
|
|
|
|
{
|
|
|
|
return m_allocated_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline T& operator[](size_t i)
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
|
|
|
return m_data[i];
|
|
|
|
}
|
2019-01-03 14:26:51 +01:00
|
|
|
inline const T& operator[](size_t i) const
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
|
|
|
return m_data[i];
|
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline T* pointer() { return m_data; }
|
|
|
|
inline const T* pointer() const
|
|
|
|
{
|
|
|
|
return m_data;
|
|
|
|
}
|
2017-08-01 14:30:58 +02:00
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline T* get_pointer_at(GUINT i)
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
|
|
|
return m_data + i;
|
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline const T* get_pointer_at(GUINT i) const
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
|
|
|
return m_data + i;
|
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline T& at(GUINT i)
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
|
|
|
return m_data[i];
|
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline const T& at(GUINT i) const
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
|
|
|
return m_data[i];
|
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline T& front()
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
|
|
|
return *m_data;
|
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline const T& front() const
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
|
|
|
return *m_data;
|
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline T& back()
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
return m_data[m_size - 1];
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline const T& back() const
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
return m_data[m_size - 1];
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void swap(GUINT i, GUINT j)
|
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
gim_swap_elements(m_data, i, j);
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline void push_back(const T& obj)
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
this->growingCheck();
|
|
|
|
m_data[m_size] = obj;
|
|
|
|
m_size++;
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//!Simply increase the m_size, doesn't call the new element constructor
|
|
|
|
inline void push_back_mem()
|
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
this->growingCheck();
|
|
|
|
m_size++;
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline void push_back_memcpy(const T& obj)
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
this->growingCheck();
|
|
|
|
gim_simd_memcpy(&m_data[m_size], &obj, sizeof(T));
|
|
|
|
m_size++;
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void pop_back()
|
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
m_size--;
|
|
|
|
m_data[m_size].~T();
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//!Simply decrease the m_size, doesn't call the deleted element destructor
|
|
|
|
inline void pop_back_mem()
|
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
m_size--;
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
//! fast erase
|
2017-08-01 14:30:58 +02:00
|
|
|
inline void erase(GUINT index)
|
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
if (index < m_size - 1)
|
|
|
|
{
|
|
|
|
swap(index, m_size - 1);
|
|
|
|
}
|
|
|
|
pop_back();
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void erase_sorted_mem(GUINT index)
|
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
m_size--;
|
|
|
|
for (GUINT i = index; i < m_size; i++)
|
|
|
|
{
|
|
|
|
gim_simd_memcpy(m_data + i, m_data + i + 1, sizeof(T));
|
|
|
|
}
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void erase_sorted(GUINT index)
|
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
m_data[index].~T();
|
|
|
|
erase_sorted_mem(index);
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void insert_mem(GUINT index)
|
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
this->growingCheck();
|
|
|
|
for (GUINT i = m_size; i > index; i--)
|
|
|
|
{
|
|
|
|
gim_simd_memcpy(m_data + i, m_data + i - 1, sizeof(T));
|
|
|
|
}
|
|
|
|
m_size++;
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline void insert(const T& obj, GUINT index)
|
2017-08-01 14:30:58 +02:00
|
|
|
{
|
2019-01-03 14:26:51 +01:00
|
|
|
insert_mem(index);
|
|
|
|
m_data[index] = obj;
|
2017-08-01 14:30:58 +02:00
|
|
|
}
|
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline void resize(GUINT size, bool call_constructor = true, const T& fillData = T())
|
|
|
|
{
|
|
|
|
if (size > m_size)
|
|
|
|
{
|
|
|
|
reserve(size);
|
|
|
|
if (call_constructor)
|
|
|
|
{
|
|
|
|
while (m_size < size)
|
|
|
|
{
|
|
|
|
m_data[m_size] = fillData;
|
|
|
|
m_size++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_size = size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (size < m_size)
|
|
|
|
{
|
|
|
|
if (call_constructor) clear_range(size);
|
|
|
|
m_size = size;
|
|
|
|
}
|
|
|
|
}
|
2017-08-01 14:30:58 +02:00
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
inline void refit()
|
|
|
|
{
|
|
|
|
resizeData(m_size);
|
|
|
|
}
|
|
|
|
};
|
2017-08-01 14:30:58 +02:00
|
|
|
|
2019-01-03 14:26:51 +01:00
|
|
|
#endif // GIM_CONTAINERS_H_INCLUDED
|