|
|
|
|
|
#ifndef DLIB_ARRAY_KERNEl_2_ |
|
#define DLIB_ARRAY_KERNEl_2_ |
|
|
|
#include "array_kernel_abstract.h" |
|
#include "../interfaces/enumerable.h" |
|
#include "../algs.h" |
|
#include "../serialize.h" |
|
#include "../sort.h" |
|
#include "../is_kind.h" |
|
|
|
namespace dlib |
|
{ |
|
|
|
template < |
|
typename T, |
|
typename mem_manager = default_memory_manager |
|
> |
|
class array : public enumerable<T> |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
typedef array kernel_1a; |
|
typedef array kernel_1a_c; |
|
typedef array kernel_2a; |
|
typedef array kernel_2a_c; |
|
typedef array sort_1a; |
|
typedef array sort_1a_c; |
|
typedef array sort_1b; |
|
typedef array sort_1b_c; |
|
typedef array sort_2a; |
|
typedef array sort_2a_c; |
|
typedef array sort_2b; |
|
typedef array sort_2b_c; |
|
typedef array expand_1a; |
|
typedef array expand_1a_c; |
|
typedef array expand_1b; |
|
typedef array expand_1b_c; |
|
typedef array expand_1c; |
|
typedef array expand_1c_c; |
|
typedef array expand_1d; |
|
typedef array expand_1d_c; |
|
|
|
|
|
|
|
|
|
typedef T type; |
|
typedef T value_type; |
|
typedef mem_manager mem_manager_type; |
|
|
|
array ( |
|
) : |
|
array_size(0), |
|
max_array_size(0), |
|
array_elements(0), |
|
pos(0), |
|
last_pos(0), |
|
_at_start(true) |
|
{} |
|
|
|
array(const array&) = delete; |
|
array& operator=(array&) = delete; |
|
|
|
array( |
|
array&& item |
|
) : array() |
|
{ |
|
swap(item); |
|
} |
|
|
|
array& operator=( |
|
array&& item |
|
) |
|
{ |
|
swap(item); |
|
return *this; |
|
} |
|
|
|
explicit array ( |
|
size_t new_size |
|
) : |
|
array_size(0), |
|
max_array_size(0), |
|
array_elements(0), |
|
pos(0), |
|
last_pos(0), |
|
_at_start(true) |
|
{ |
|
resize(new_size); |
|
} |
|
|
|
~array ( |
|
); |
|
|
|
void clear ( |
|
); |
|
|
|
inline const T& operator[] ( |
|
size_t pos |
|
) const; |
|
|
|
inline T& operator[] ( |
|
size_t pos |
|
); |
|
|
|
void set_size ( |
|
size_t size |
|
); |
|
|
|
inline size_t max_size( |
|
) const; |
|
|
|
void set_max_size( |
|
size_t max |
|
); |
|
|
|
void swap ( |
|
array& item |
|
); |
|
|
|
|
|
inline size_t size ( |
|
) const; |
|
|
|
inline bool at_start ( |
|
) const; |
|
|
|
inline void reset ( |
|
) const; |
|
|
|
bool current_element_valid ( |
|
) const; |
|
|
|
inline const T& element ( |
|
) const; |
|
|
|
inline T& element ( |
|
); |
|
|
|
bool move_next ( |
|
) const; |
|
|
|
void sort ( |
|
); |
|
|
|
void resize ( |
|
size_t new_size |
|
); |
|
|
|
const T& back ( |
|
) const; |
|
|
|
T& back ( |
|
); |
|
|
|
void pop_back ( |
|
); |
|
|
|
void pop_back ( |
|
T& item |
|
); |
|
|
|
void push_back ( |
|
T& item |
|
); |
|
|
|
void push_back ( |
|
T&& item |
|
); |
|
|
|
typedef T* iterator; |
|
typedef const T* const_iterator; |
|
iterator begin() { return array_elements; } |
|
const_iterator begin() const { return array_elements; } |
|
iterator end() { return array_elements+array_size; } |
|
const_iterator end() const { return array_elements+array_size; } |
|
|
|
private: |
|
|
|
typename mem_manager::template rebind<T>::other pool; |
|
|
|
|
|
size_t array_size; |
|
size_t max_array_size; |
|
T* array_elements; |
|
|
|
mutable T* pos; |
|
T* last_pos; |
|
mutable bool _at_start; |
|
|
|
}; |
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
inline void swap ( |
|
array<T,mem_manager>& a, |
|
array<T,mem_manager>& b |
|
) { a.swap(b); } |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void serialize ( |
|
const array<T,mem_manager>& item, |
|
std::ostream& out |
|
) |
|
{ |
|
try |
|
{ |
|
serialize(item.max_size(),out); |
|
serialize(item.size(),out); |
|
|
|
for (size_t i = 0; i < item.size(); ++i) |
|
serialize(item[i],out); |
|
} |
|
catch (serialization_error& e) |
|
{ |
|
throw serialization_error(e.info + "\n while serializing object of type array"); |
|
} |
|
} |
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void deserialize ( |
|
array<T,mem_manager>& item, |
|
std::istream& in |
|
) |
|
{ |
|
try |
|
{ |
|
size_t max_size, size; |
|
deserialize(max_size,in); |
|
deserialize(size,in); |
|
item.set_max_size(max_size); |
|
item.set_size(size); |
|
for (size_t i = 0; i < size; ++i) |
|
deserialize(item[i],in); |
|
} |
|
catch (serialization_error& e) |
|
{ |
|
item.clear(); |
|
throw serialization_error(e.info + "\n while deserializing object of type array"); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
array<T,mem_manager>:: |
|
~array ( |
|
) |
|
{ |
|
if (array_elements) |
|
{ |
|
pool.deallocate_array(array_elements); |
|
} |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void array<T,mem_manager>:: |
|
clear ( |
|
) |
|
{ |
|
reset(); |
|
last_pos = 0; |
|
array_size = 0; |
|
if (array_elements) |
|
{ |
|
pool.deallocate_array(array_elements); |
|
} |
|
array_elements = 0; |
|
max_array_size = 0; |
|
|
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
const T& array<T,mem_manager>:: |
|
operator[] ( |
|
size_t pos |
|
) const |
|
{ |
|
|
|
DLIB_ASSERT( pos < this->size() , |
|
"\tconst T& array::operator[]" |
|
<< "\n\tpos must < size()" |
|
<< "\n\tpos: " << pos |
|
<< "\n\tsize(): " << this->size() |
|
<< "\n\tthis: " << this |
|
); |
|
|
|
return array_elements[pos]; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
T& array<T,mem_manager>:: |
|
operator[] ( |
|
size_t pos |
|
) |
|
{ |
|
|
|
DLIB_ASSERT( pos < this->size() , |
|
"\tT& array::operator[]" |
|
<< "\n\tpos must be < size()" |
|
<< "\n\tpos: " << pos |
|
<< "\n\tsize(): " << this->size() |
|
<< "\n\tthis: " << this |
|
); |
|
|
|
return array_elements[pos]; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void array<T,mem_manager>:: |
|
set_size ( |
|
size_t size |
|
) |
|
{ |
|
|
|
DLIB_CASSERT(( size <= this->max_size() ), |
|
"\tvoid array::set_size" |
|
<< "\n\tsize must be <= max_size()" |
|
<< "\n\tsize: " << size |
|
<< "\n\tmax size: " << this->max_size() |
|
<< "\n\tthis: " << this |
|
); |
|
|
|
reset(); |
|
array_size = size; |
|
if (size > 0) |
|
last_pos = array_elements + size - 1; |
|
else |
|
last_pos = 0; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
size_t array<T,mem_manager>:: |
|
size ( |
|
) const |
|
{ |
|
return array_size; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void array<T,mem_manager>:: |
|
set_max_size( |
|
size_t max |
|
) |
|
{ |
|
reset(); |
|
array_size = 0; |
|
last_pos = 0; |
|
if (max != 0) |
|
{ |
|
|
|
if (max != max_array_size) |
|
{ |
|
if (array_elements) |
|
{ |
|
pool.deallocate_array(array_elements); |
|
} |
|
|
|
try { array_elements = pool.allocate_array(max); } |
|
catch (...) { array_elements = 0; max_array_size = 0; throw; } |
|
max_array_size = max; |
|
} |
|
|
|
} |
|
|
|
else |
|
{ |
|
if (array_elements) |
|
pool.deallocate_array(array_elements); |
|
max_array_size = 0; |
|
array_elements = 0; |
|
} |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
size_t array<T,mem_manager>:: |
|
max_size ( |
|
) const |
|
{ |
|
return max_array_size; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void array<T,mem_manager>:: |
|
swap ( |
|
array<T,mem_manager>& item |
|
) |
|
{ |
|
auto array_size_temp = item.array_size; |
|
auto max_array_size_temp = item.max_array_size; |
|
T* array_elements_temp = item.array_elements; |
|
|
|
item.array_size = array_size; |
|
item.max_array_size = max_array_size; |
|
item.array_elements = array_elements; |
|
|
|
array_size = array_size_temp; |
|
max_array_size = max_array_size_temp; |
|
array_elements = array_elements_temp; |
|
|
|
exchange(_at_start,item._at_start); |
|
exchange(pos,item.pos); |
|
exchange(last_pos,item.last_pos); |
|
pool.swap(item.pool); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
bool array<T,mem_manager>:: |
|
at_start ( |
|
) const |
|
{ |
|
return _at_start; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void array<T,mem_manager>:: |
|
reset ( |
|
) const |
|
{ |
|
_at_start = true; |
|
pos = 0; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
bool array<T,mem_manager>:: |
|
current_element_valid ( |
|
) const |
|
{ |
|
return pos != 0; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
const T& array<T,mem_manager>:: |
|
element ( |
|
) const |
|
{ |
|
|
|
DLIB_ASSERT(this->current_element_valid(), |
|
"\tconst T& array::element()" |
|
<< "\n\tThe current element must be valid if you are to access it." |
|
<< "\n\tthis: " << this |
|
); |
|
|
|
return *pos; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
T& array<T,mem_manager>:: |
|
element ( |
|
) |
|
{ |
|
|
|
DLIB_ASSERT(this->current_element_valid(), |
|
"\tT& array::element()" |
|
<< "\n\tThe current element must be valid if you are to access it." |
|
<< "\n\tthis: " << this |
|
); |
|
|
|
return *pos; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
bool array<T,mem_manager>:: |
|
move_next ( |
|
) const |
|
{ |
|
if (!_at_start) |
|
{ |
|
if (pos < last_pos) |
|
{ |
|
++pos; |
|
return true; |
|
} |
|
else |
|
{ |
|
pos = 0; |
|
return false; |
|
} |
|
} |
|
else |
|
{ |
|
_at_start = false; |
|
if (array_size > 0) |
|
{ |
|
pos = array_elements; |
|
return true; |
|
} |
|
else |
|
{ |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void array<T,mem_manager>:: |
|
sort ( |
|
) |
|
{ |
|
if (this->size() > 1) |
|
{ |
|
|
|
dlib::qsort_array(*this,0,this->size()-1); |
|
} |
|
this->reset(); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void array<T,mem_manager>:: |
|
resize ( |
|
size_t new_size |
|
) |
|
{ |
|
if (this->max_size() < new_size) |
|
{ |
|
array temp; |
|
temp.set_max_size(new_size); |
|
temp.set_size(new_size); |
|
for (size_t i = 0; i < this->size(); ++i) |
|
{ |
|
exchange((*this)[i],temp[i]); |
|
} |
|
temp.swap(*this); |
|
} |
|
else |
|
{ |
|
this->set_size(new_size); |
|
} |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
T& array<T,mem_manager>:: |
|
back ( |
|
) |
|
{ |
|
|
|
DLIB_ASSERT( this->size() > 0 , |
|
"\tT& array::back()" |
|
<< "\n\tsize() must be bigger than 0" |
|
<< "\n\tsize(): " << this->size() |
|
<< "\n\tthis: " << this |
|
); |
|
|
|
return (*this)[this->size()-1]; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
const T& array<T,mem_manager>:: |
|
back ( |
|
) const |
|
{ |
|
|
|
DLIB_ASSERT( this->size() > 0 , |
|
"\tconst T& array::back()" |
|
<< "\n\tsize() must be bigger than 0" |
|
<< "\n\tsize(): " << this->size() |
|
<< "\n\tthis: " << this |
|
); |
|
|
|
return (*this)[this->size()-1]; |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void array<T,mem_manager>:: |
|
pop_back ( |
|
T& item |
|
) |
|
{ |
|
|
|
DLIB_ASSERT( this->size() > 0 , |
|
"\tvoid array::pop_back()" |
|
<< "\n\tsize() must be bigger than 0" |
|
<< "\n\tsize(): " << this->size() |
|
<< "\n\tthis: " << this |
|
); |
|
|
|
exchange(item,(*this)[this->size()-1]); |
|
this->set_size(this->size()-1); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void array<T,mem_manager>:: |
|
pop_back ( |
|
) |
|
{ |
|
|
|
DLIB_ASSERT( this->size() > 0 , |
|
"\tvoid array::pop_back()" |
|
<< "\n\tsize() must be bigger than 0" |
|
<< "\n\tsize(): " << this->size() |
|
<< "\n\tthis: " << this |
|
); |
|
|
|
this->set_size(this->size()-1); |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void array<T,mem_manager>:: |
|
push_back ( |
|
T& item |
|
) |
|
{ |
|
if (this->max_size() == this->size()) |
|
{ |
|
|
|
array temp; |
|
temp.set_max_size(this->size()*2 + 1); |
|
temp.set_size(this->size()+1); |
|
for (size_t i = 0; i < this->size(); ++i) |
|
{ |
|
exchange((*this)[i],temp[i]); |
|
} |
|
exchange(item,temp[temp.size()-1]); |
|
temp.swap(*this); |
|
} |
|
else |
|
{ |
|
this->set_size(this->size()+1); |
|
exchange(item,(*this)[this->size()-1]); |
|
} |
|
} |
|
|
|
|
|
|
|
template < |
|
typename T, |
|
typename mem_manager |
|
> |
|
void array<T,mem_manager>:: |
|
push_back ( |
|
T&& item |
|
) { push_back(item); } |
|
|
|
|
|
|
|
template <typename T, typename MM> |
|
struct is_array <array<T,MM> > |
|
{ |
|
const static bool value = true; |
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
#endif |
|
|
|
|