2010-11-20 10:37:14 +00:00
|
|
|
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
|
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
2011-04-13 18:22:10 +00:00
|
|
|
#ifndef BASE_TL_ARRAY_H
|
|
|
|
#define BASE_TL_ARRAY_H
|
2009-06-15 06:45:44 +00:00
|
|
|
|
2014-06-16 11:29:18 +00:00
|
|
|
#include "base/tl/range.h"
|
|
|
|
#include "base/tl/allocator.h"
|
2009-06-15 06:45:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Class: array
|
|
|
|
Normal dynamic array class
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
Remarks:
|
|
|
|
- Grows 50% each time it needs to fit new items
|
2011-04-13 18:37:12 +00:00
|
|
|
- Use set_size() if you know how many elements
|
2009-06-15 06:45:44 +00:00
|
|
|
- Use optimize() to reduce the needed space.
|
|
|
|
*/
|
|
|
|
template <class T, class ALLOCATOR = allocator_default<T> >
|
|
|
|
class array : private ALLOCATOR
|
|
|
|
{
|
|
|
|
void init()
|
|
|
|
{
|
|
|
|
list = 0x0;
|
|
|
|
clear();
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
public:
|
|
|
|
typedef plain_range<T> range;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: array constructor
|
|
|
|
*/
|
|
|
|
array()
|
|
|
|
{
|
|
|
|
init();
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
/*
|
|
|
|
Function: array copy constructor
|
|
|
|
*/
|
|
|
|
array(const array &other)
|
|
|
|
{
|
|
|
|
init();
|
|
|
|
set_size(other.size());
|
|
|
|
for(int i = 0; i < size(); i++)
|
|
|
|
(*this)[i] = other[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: array destructor
|
|
|
|
*/
|
|
|
|
~array()
|
|
|
|
{
|
|
|
|
ALLOCATOR::free_array(list);
|
|
|
|
list = 0x0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: delete_all
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
Remarks:
|
|
|
|
- Invalidates ranges
|
|
|
|
*/
|
|
|
|
void delete_all()
|
|
|
|
{
|
|
|
|
for(int i = 0; i < size(); i++)
|
|
|
|
delete list[i];
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: clear
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
Remarks:
|
|
|
|
- Invalidates ranges
|
|
|
|
*/
|
|
|
|
void clear()
|
|
|
|
{
|
|
|
|
ALLOCATOR::free_array(list);
|
|
|
|
list_size = 1;
|
|
|
|
list = ALLOCATOR::alloc_array(list_size);
|
|
|
|
num_elements = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: size
|
|
|
|
*/
|
|
|
|
int size() const
|
|
|
|
{
|
|
|
|
return num_elements;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: remove_index_fast
|
|
|
|
|
|
|
|
Remarks:
|
|
|
|
- Invalidates ranges
|
|
|
|
*/
|
|
|
|
void remove_index_fast(int index)
|
|
|
|
{
|
|
|
|
list[index] = list[num_elements-1];
|
|
|
|
set_size(size()-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: remove_fast
|
|
|
|
|
|
|
|
Remarks:
|
|
|
|
- Invalidates ranges
|
|
|
|
*/
|
|
|
|
void remove_fast(const T& item)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < size(); i++)
|
|
|
|
if(list[i] == item)
|
|
|
|
{
|
|
|
|
remove_index_fast(i);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: remove_index
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
Remarks:
|
|
|
|
- Invalidates ranges
|
|
|
|
*/
|
|
|
|
void remove_index(int index)
|
|
|
|
{
|
|
|
|
for(int i = index+1; i < num_elements; i++)
|
|
|
|
list[i-1] = list[i];
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
set_size(size()-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: remove
|
|
|
|
|
|
|
|
Remarks:
|
|
|
|
- Invalidates ranges
|
|
|
|
*/
|
|
|
|
bool remove(const T& item)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < size(); i++)
|
|
|
|
if(list[i] == item)
|
|
|
|
{
|
|
|
|
remove_index(i);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: add
|
|
|
|
Adds an item to the array.
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
Arguments:
|
|
|
|
item - Item to add.
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
Remarks:
|
|
|
|
- Invalidates ranges
|
|
|
|
- See remarks about <array> how the array grows.
|
|
|
|
*/
|
|
|
|
int add(const T& item)
|
|
|
|
{
|
|
|
|
incsize();
|
2010-05-29 07:25:38 +00:00
|
|
|
set_size(size()+1);
|
2009-06-15 06:45:44 +00:00
|
|
|
list[num_elements-1] = item;
|
|
|
|
return num_elements-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: insert
|
|
|
|
Inserts an item into the array at a specified location.
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
Arguments:
|
2011-04-13 18:37:12 +00:00
|
|
|
item - Item to insert.
|
2009-06-15 06:45:44 +00:00
|
|
|
r - Range where to insert the item
|
|
|
|
|
|
|
|
Remarks:
|
|
|
|
- Invalidates ranges
|
|
|
|
- See remarks about <array> how the array grows.
|
|
|
|
*/
|
|
|
|
int insert(const T& item, range r)
|
|
|
|
{
|
|
|
|
if(r.empty())
|
|
|
|
return add(item);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
int index = (int)(&r.front()-list);
|
|
|
|
incsize();
|
2010-05-29 07:25:38 +00:00
|
|
|
set_size(size()+1);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
for(int i = num_elements-1; i > index; i--)
|
|
|
|
list[i] = list[i-1];
|
|
|
|
|
|
|
|
list[index] = item;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
return num_elements-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: operator[]
|
|
|
|
*/
|
|
|
|
T& operator[] (int index)
|
|
|
|
{
|
|
|
|
return list[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: const operator[]
|
|
|
|
*/
|
|
|
|
const T& operator[] (int index) const
|
|
|
|
{
|
|
|
|
return list[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: base_ptr
|
|
|
|
*/
|
|
|
|
T *base_ptr()
|
|
|
|
{
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: base_ptr
|
|
|
|
*/
|
|
|
|
const T *base_ptr() const
|
|
|
|
{
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: set_size
|
|
|
|
Resizes the array to the specified size.
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
Arguments:
|
|
|
|
new_size - The new size for the array.
|
|
|
|
*/
|
|
|
|
void set_size(int new_size)
|
|
|
|
{
|
2011-03-27 14:42:47 +00:00
|
|
|
if(list_size < new_size)
|
|
|
|
alloc(new_size);
|
2009-06-15 06:45:44 +00:00
|
|
|
num_elements = new_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: hint_size
|
|
|
|
Allocates the number of elements wanted but
|
|
|
|
does not increase the list size.
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
Arguments:
|
|
|
|
hint - Size to allocate.
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
Remarks:
|
|
|
|
- If the hint is smaller then the number of elements, nothing will be done.
|
|
|
|
- Invalidates ranges
|
|
|
|
*/
|
|
|
|
void hint_size(int hint)
|
|
|
|
{
|
|
|
|
if(num_elements < hint)
|
|
|
|
alloc(hint);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: optimize
|
|
|
|
Removes unnessasary data, returns how many bytes was earned.
|
|
|
|
|
|
|
|
Remarks:
|
|
|
|
- Invalidates ranges
|
|
|
|
*/
|
|
|
|
int optimize()
|
|
|
|
{
|
|
|
|
int before = memusage();
|
|
|
|
alloc(num_elements);
|
|
|
|
return before - memusage();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: memusage
|
|
|
|
Returns how much memory this dynamic array is using
|
|
|
|
*/
|
|
|
|
int memusage()
|
|
|
|
{
|
2010-07-05 18:57:07 +00:00
|
|
|
return sizeof(array) + sizeof(T)*list_size;
|
2009-06-15 06:45:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function: operator=(array)
|
|
|
|
|
|
|
|
Remarks:
|
|
|
|
- Invalidates ranges
|
|
|
|
*/
|
|
|
|
array &operator = (const array &other)
|
|
|
|
{
|
|
|
|
set_size(other.size());
|
|
|
|
for(int i = 0; i < size(); i++)
|
|
|
|
(*this)[i] = other[i];
|
|
|
|
return *this;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
/*
|
|
|
|
Function: all
|
|
|
|
Returns a range that contains the whole array.
|
|
|
|
*/
|
|
|
|
range all() { return range(list, list+num_elements); }
|
|
|
|
protected:
|
|
|
|
|
|
|
|
void incsize()
|
|
|
|
{
|
|
|
|
if(num_elements == list_size)
|
|
|
|
{
|
|
|
|
if(list_size < 2)
|
|
|
|
alloc(list_size+1);
|
|
|
|
else
|
|
|
|
alloc(list_size+list_size/2);
|
2011-04-13 18:37:12 +00:00
|
|
|
}
|
2009-06-15 06:45:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void alloc(int new_len)
|
|
|
|
{
|
|
|
|
list_size = new_len;
|
|
|
|
T *new_list = ALLOCATOR::alloc_array(list_size);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
int end = num_elements < list_size ? num_elements : list_size;
|
|
|
|
for(int i = 0; i < end; i++)
|
|
|
|
new_list[i] = list[i];
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-06-15 06:45:44 +00:00
|
|
|
ALLOCATOR::free_array(list);
|
|
|
|
|
|
|
|
num_elements = num_elements < list_size ? num_elements : list_size;
|
|
|
|
list = new_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
T *list;
|
|
|
|
int list_size;
|
|
|
|
int num_elements;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // TL_FILE_ARRAY_HPP
|