Commit fb266ade authored by Davis King's avatar Davis King

Turned the array into a single implementation object. Now arrays can be

created using the normal array<type> obj; syntax.  Additionally, all extensions
were put into the array object directly and the implementation is the
flat single array implementation.
parent 98d63d48
...@@ -3,103 +3,7 @@ ...@@ -3,103 +3,7 @@
#ifndef DLIB_ARRAy_ #ifndef DLIB_ARRAy_
#define DLIB_ARRAy_ #define DLIB_ARRAy_
#include "array/array_kernel_1.h"
#include "array/array_kernel_2.h" #include "array/array_kernel_2.h"
#include "array/array_kernel_c.h"
#include "array/array_sort_1.h"
#include "array/array_sort_2.h"
#include "array/array_expand_1.h"
#include "array/array_expand_c.h"
#include "algs.h"
namespace dlib
{
template <
typename T,
typename mem_manager = default_memory_manager
>
class array
{
array() {}
public:
//----------- kernels ---------------
// kernel_1a
typedef array_kernel_1<T,mem_manager>
kernel_1a;
typedef array_kernel_c<kernel_1a >
kernel_1a_c;
// kernel_2a
typedef array_kernel_2<T,mem_manager>
kernel_2a;
typedef array_kernel_c<kernel_2a >
kernel_2a_c;
//---------- extensions ------------
// sort_1 extend kernel_1a
typedef array_sort_1<kernel_1a>
sort_1a;
typedef array_sort_1<kernel_1a_c>
sort_1a_c;
// sort_1 extend kernel_2a
typedef array_sort_1<kernel_2a>
sort_1b;
typedef array_sort_1<kernel_2a_c>
sort_1b_c;
// sort_2 extend kernel_1a
typedef array_sort_2<kernel_1a>
sort_2a;
typedef array_sort_2<kernel_1a_c>
sort_2a_c;
// sort_2 extend kernel_2a
typedef array_sort_2<kernel_2a>
sort_2b;
typedef array_sort_2<kernel_2a_c>
sort_2b_c;
// expand_1 extend sort_1a
typedef array_expand_1<sort_1a>
expand_1a;
typedef array_expand_c<array_kernel_c<expand_1a> >
expand_1a_c;
// expand_1 extend sort_1b
typedef array_expand_1<sort_1b>
expand_1b;
typedef array_expand_c<array_kernel_c<expand_1b> >
expand_1b_c;
// expand_1 extend sort_2a
typedef array_expand_1<sort_2a>
expand_1c;
typedef array_expand_c<array_kernel_c<expand_1c> >
expand_1c_c;
// expand_1 extend sort_2b
typedef array_expand_1<sort_2b>
expand_1d;
typedef array_expand_c<array_kernel_c<expand_1d> >
expand_1d_c;
};
}
#endif // DLIB_ARRAy_ #endif // DLIB_ARRAy_
// Copyright (C) 2003 Davis E. King (davis@dlib.net) // Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: GNU LGPL See LICENSE.txt for the full license. // License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ARRAY_KERNEl_2_ #ifndef DLIB_ARRAY_KERNEl_2_
#define DLIB_ARRAY_KERNEl_2_ #define DLIB_ARRAY_KERNEl_2_
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "../interfaces/enumerable.h" #include "../interfaces/enumerable.h"
#include "../algs.h" #include "../algs.h"
#include "../serialize.h" #include "../serialize.h"
#include "../sort.h"
namespace dlib namespace dlib
{ {
...@@ -15,7 +16,7 @@ namespace dlib ...@@ -15,7 +16,7 @@ namespace dlib
typename T, typename T,
typename mem_manager = default_memory_manager typename mem_manager = default_memory_manager
> >
class array_kernel_2 : public enumerable<T> class array : public enumerable<T>
{ {
/*! /*!
...@@ -49,10 +50,35 @@ namespace dlib ...@@ -49,10 +50,35 @@ namespace dlib
public: public:
// These typedefs are here for backwards compatibility with old versions of dlib.
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 type;
typedef mem_manager mem_manager_type; typedef mem_manager mem_manager_type;
array_kernel_2 ( array (
) : ) :
array_size(0), array_size(0),
max_array_size(0), max_array_size(0),
...@@ -62,7 +88,7 @@ namespace dlib ...@@ -62,7 +88,7 @@ namespace dlib
_at_start(true) _at_start(true)
{} {}
virtual ~array_kernel_2 ( ~array (
); );
void clear ( void clear (
...@@ -88,7 +114,7 @@ namespace dlib ...@@ -88,7 +114,7 @@ namespace dlib
); );
void swap ( void swap (
array_kernel_2& item array& item
); );
// functions from the enumerable interface // functions from the enumerable interface
...@@ -113,6 +139,30 @@ namespace dlib ...@@ -113,6 +139,30 @@ namespace dlib
bool move_next ( bool move_next (
) const; ) const;
void sort (
);
void resize (
unsigned long new_size
);
const T& back (
) const;
T& back (
);
void pop_back (
);
void pop_back (
T& item
);
void push_back (
T& item
);
private: private:
typename mem_manager::template rebind<T>::other pool; typename mem_manager::template rebind<T>::other pool;
...@@ -127,8 +177,8 @@ namespace dlib ...@@ -127,8 +177,8 @@ namespace dlib
mutable bool _at_start; mutable bool _at_start;
// restricted functions // restricted functions
array_kernel_2(array_kernel_2<T>&); // copy constructor array(array<T>&); // copy constructor
array_kernel_2<T>& operator=(array_kernel_2<T>&); // assignment operator array<T>& operator=(array<T>&); // assignment operator
}; };
...@@ -137,8 +187,8 @@ namespace dlib ...@@ -137,8 +187,8 @@ namespace dlib
typename mem_manager typename mem_manager
> >
inline void swap ( inline void swap (
array_kernel_2<T,mem_manager>& a, array<T,mem_manager>& a,
array_kernel_2<T,mem_manager>& b array<T,mem_manager>& b
) { a.swap(b); } ) { a.swap(b); }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -148,7 +198,7 @@ namespace dlib ...@@ -148,7 +198,7 @@ namespace dlib
typename mem_manager typename mem_manager
> >
void serialize ( void serialize (
const array_kernel_2<T,mem_manager>& item, const array<T,mem_manager>& item,
std::ostream& out std::ostream& out
) )
{ {
...@@ -162,7 +212,7 @@ namespace dlib ...@@ -162,7 +212,7 @@ namespace dlib
} }
catch (serialization_error e) catch (serialization_error e)
{ {
throw serialization_error(e.info + "\n while serializing object of type array_kernel_2"); throw serialization_error(e.info + "\n while serializing object of type array");
} }
} }
...@@ -171,7 +221,7 @@ namespace dlib ...@@ -171,7 +221,7 @@ namespace dlib
typename mem_manager typename mem_manager
> >
void deserialize ( void deserialize (
array_kernel_2<T,mem_manager>& item, array<T,mem_manager>& item,
std::istream& in std::istream& in
) )
{ {
...@@ -188,7 +238,7 @@ namespace dlib ...@@ -188,7 +238,7 @@ namespace dlib
catch (serialization_error e) catch (serialization_error e)
{ {
item.clear(); item.clear();
throw serialization_error(e.info + "\n while deserializing object of type array_kernel_2"); throw serialization_error(e.info + "\n while deserializing object of type array");
} }
} }
...@@ -202,8 +252,8 @@ namespace dlib ...@@ -202,8 +252,8 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
array_kernel_2<T,mem_manager>:: array<T,mem_manager>::
~array_kernel_2 ( ~array (
) )
{ {
if (array_elements) if (array_elements)
...@@ -218,7 +268,7 @@ namespace dlib ...@@ -218,7 +268,7 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
void array_kernel_2<T,mem_manager>:: void array<T,mem_manager>::
clear ( clear (
) )
{ {
...@@ -240,11 +290,20 @@ namespace dlib ...@@ -240,11 +290,20 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
const T& array_kernel_2<T,mem_manager>:: const T& array<T,mem_manager>::
operator[] ( operator[] (
unsigned long pos unsigned long pos
) const ) const
{ {
// make sure requires clause is not broken
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]; return array_elements[pos];
} }
...@@ -254,11 +313,20 @@ namespace dlib ...@@ -254,11 +313,20 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
T& array_kernel_2<T,mem_manager>:: T& array<T,mem_manager>::
operator[] ( operator[] (
unsigned long pos unsigned long pos
) )
{ {
// make sure requires clause is not broken
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]; return array_elements[pos];
} }
...@@ -268,11 +336,20 @@ namespace dlib ...@@ -268,11 +336,20 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
void array_kernel_2<T,mem_manager>:: void array<T,mem_manager>::
set_size ( set_size (
unsigned long size unsigned long size
) )
{ {
// make sure requires clause is not broken
DLIB_ASSERT(( 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(); reset();
array_size = size; array_size = size;
if (size > 0) if (size > 0)
...@@ -287,7 +364,7 @@ namespace dlib ...@@ -287,7 +364,7 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
unsigned long array_kernel_2<T,mem_manager>:: unsigned long array<T,mem_manager>::
size ( size (
) const ) const
{ {
...@@ -300,7 +377,7 @@ namespace dlib ...@@ -300,7 +377,7 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
void array_kernel_2<T,mem_manager>:: void array<T,mem_manager>::
set_max_size( set_max_size(
unsigned long max unsigned long max
) )
...@@ -340,7 +417,7 @@ namespace dlib ...@@ -340,7 +417,7 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
unsigned long array_kernel_2<T,mem_manager>:: unsigned long array<T,mem_manager>::
max_size ( max_size (
) const ) const
{ {
...@@ -353,9 +430,9 @@ namespace dlib ...@@ -353,9 +430,9 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
void array_kernel_2<T,mem_manager>:: void array<T,mem_manager>::
swap ( swap (
array_kernel_2<T,mem_manager>& item array<T,mem_manager>& item
) )
{ {
unsigned long array_size_temp = item.array_size; unsigned long array_size_temp = item.array_size;
...@@ -386,7 +463,7 @@ namespace dlib ...@@ -386,7 +463,7 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
bool array_kernel_2<T,mem_manager>:: bool array<T,mem_manager>::
at_start ( at_start (
) const ) const
{ {
...@@ -399,7 +476,7 @@ namespace dlib ...@@ -399,7 +476,7 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
void array_kernel_2<T,mem_manager>:: void array<T,mem_manager>::
reset ( reset (
) const ) const
{ {
...@@ -413,7 +490,7 @@ namespace dlib ...@@ -413,7 +490,7 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
bool array_kernel_2<T,mem_manager>:: bool array<T,mem_manager>::
current_element_valid ( current_element_valid (
) const ) const
{ {
...@@ -426,10 +503,17 @@ namespace dlib ...@@ -426,10 +503,17 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
const T& array_kernel_2<T,mem_manager>:: const T& array<T,mem_manager>::
element ( element (
) const ) const
{ {
// make sure requires clause is not broken
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; return *pos;
} }
...@@ -439,10 +523,17 @@ namespace dlib ...@@ -439,10 +523,17 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
T& array_kernel_2<T,mem_manager>:: T& array<T,mem_manager>::
element ( element (
) )
{ {
// make sure requires clause is not broken
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; return *pos;
} }
...@@ -452,7 +543,7 @@ namespace dlib ...@@ -452,7 +543,7 @@ namespace dlib
typename T, typename T,
typename mem_manager typename mem_manager
> >
bool array_kernel_2<T,mem_manager>:: bool array<T,mem_manager>::
move_next ( move_next (
) const ) const
{ {
...@@ -484,6 +575,173 @@ namespace dlib ...@@ -484,6 +575,173 @@ namespace dlib
} }
} }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Yet more functions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
sort (
)
{
if (this->size() > 1)
{
// call the quick sort function for arrays that is in algs.h
dlib::qsort_array(*this,0,this->size()-1);
}
this->reset();
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
resize (
unsigned long new_size
)
{
if (this->max_size() < new_size)
{
array temp;
temp.set_max_size(new_size);
temp.set_size(new_size);
for (unsigned long 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 (
)
{
// make sure requires clause is not broken
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
{
// make sure requires clause is not broken
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
)
{
// make sure requires clause is not broken
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 (
)
{
// make sure requires clause is not broken
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())
{
// double the size of the array
array temp;
temp.set_max_size(this->size()*2 + 1);
temp.set_size(this->size()+1);
for (unsigned long 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]);
}
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
} }
......
...@@ -28,8 +28,8 @@ namespace dlib ...@@ -28,8 +28,8 @@ namespace dlib
mem_manager::type can be set to anything. mem_manager::type can be set to anything.
POINTERS AND REFERENCES TO INTERNAL DATA POINTERS AND REFERENCES TO INTERNAL DATA
swap(), max_size(), set_size(), and operator[] functions do front(), back(), swap(), max_size(), set_size(), and operator[]
not invalidate pointers or references to internal data. functions do not invalidate pointers or references to internal data.
All other functions have no such guarantee. All other functions have no such guarantee.
INITIAL VALUE INITIAL VALUE
...@@ -66,7 +66,7 @@ namespace dlib ...@@ -66,7 +66,7 @@ namespace dlib
- std::bad_alloc or any exception thrown by T's constructor - std::bad_alloc or any exception thrown by T's constructor
!*/ !*/
virtual ~array ( ~array (
); );
/*! /*!
ensures ensures
...@@ -153,6 +153,96 @@ namespace dlib ...@@ -153,6 +153,96 @@ namespace dlib
- swaps *this and item - swaps *this and item
!*/ !*/
void sort (
);
/*!
requires
- T must be a type with that is comparable via operator<
ensures
- for all elements in #*this the ith element is <= the i+1 element
- #at_start() == true
throws
- std::bad_alloc or any exception thrown by T's constructor
data may be lost if sort() throws
!*/
void resize (
unsigned long new_size
);
/*!
ensures
- #size() == new_size
- #max_size() == max(new_size,max_size())
- for all i < size() && i < new_size:
- #(*this)[i] == (*this)[i]
(i.e. All the original elements of *this which were at index
values less than new_size are unmodified.)
- for all valid i >= size():
- #(*this)[i] has an undefined value
(i.e. any new elements of the array have an undefined value)
throws
- std::bad_alloc or any exception thrown by T's constructor.
If an exception is thrown then it has no effect on *this.
!*/
const T& back (
) const;
/*!
requires
- size() != 0
ensures
- returns a const reference to (*this)[size()-1]
!*/
T& back (
);
/*!
requires
- size() != 0
ensures
- returns a non-const reference to (*this)[size()-1]
!*/
void pop_back (
T& item
);
/*!
requires
- size() != 0
ensures
- #size() == size() - 1
- swaps (*this)[size()-1] into item
- All elements with an index less than size()-1 are
unmodified by this operation.
!*/
void pop_back (
);
/*!
requires
- size() != 0
ensures
- #size() == size() - 1
- All elements with an index less than size()-1 are
unmodified by this operation.
!*/
void push_back (
T& item
);
/*!
ensures
- #size() == size()+1
- swaps item into (*this)[#size()-1]
- #back() == item
- #item has some undefined value (whatever happens to
get swapped out of the array)
throws
- std::bad_alloc or any exception thrown by T's constructor.
If an exception is thrown then it has no effect on *this.
!*/
private: private:
// restricted functions // restricted functions
......
...@@ -590,7 +590,22 @@ namespace ...@@ -590,7 +590,22 @@ namespace
DLIB_TEST(a1.size() == 0); DLIB_TEST(a1.size() == 0);
} }
}
struct stuff
{
int whatever;
};
void another_array_test()
{
array<stuff> a;
a.resize(5);
a[0].whatever = 0;
stuff temp;
temp.whatever = 99;
a.push_back(temp);
DLIB_TEST(a.size() == 6);
DLIB_TEST(a[5].whatever == 99);
} }
...@@ -606,41 +621,12 @@ namespace ...@@ -606,41 +621,12 @@ namespace
void perform_test ( void perform_test (
) )
{ {
// test a checking version first for good measure
dlog << LINFO << "testing expand_1a_c";
print_spinner();
array_expand_test<array<unsigned long>::expand_1a_c>();
dlog << LINFO << "testing expand_1a";
print_spinner();
array_expand_test<array<unsigned long>::expand_1a>();
dlog << LINFO << "testing expand_1b";
print_spinner();
array_expand_test<array<unsigned long>::expand_1b>();
dlog << LINFO << "testing expand_1b_c";
print_spinner();
array_expand_test<array<unsigned long>::expand_1b_c>();
dlog << LINFO << "testing expand_1c";
print_spinner();
array_expand_test<array<unsigned long>::expand_1c>();
dlog << LINFO << "testing expand_1c_c";
print_spinner(); print_spinner();
array_expand_test<array<unsigned long>::expand_1c_c>(); another_array_test();
dlog << LINFO << "testing expand_1d";
print_spinner();
array_expand_test<array<unsigned long>::expand_1d>();
dlog << LINFO << "testing expand_1d_c";
print_spinner();
array_expand_test<array<unsigned long>::expand_1d_c>();
// test a checking version first for good measure
print_spinner(); print_spinner();
array_expand_test<array<unsigned long> >();
} }
} a; } a;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment