// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ARRAY2D_KERNEl_C_
#define DLIB_ARRAY2D_KERNEl_C_
#include "array2d_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
#include "../interfaces/enumerable.h"
namespace dlib
{
template <
typename array2d_base // is an implementation of array2d_kernel_abstract.h
>
class array2d_kernel_c : public enumerable<typename array2d_base::type>
{
/*!
CONVENTION
- if (obj.size() > 0) then
- rows == an array of size obj.nr() row objects and
each row object in the array has a valid pointer to its
associated row in obj.
- else
- rows == 0
!*/
typedef typename array2d_base::type T;
public:
typedef typename array2d_base::type type;
typedef typename array2d_base::mem_manager_type mem_manager_type;
// -----------------------------------
class row
{
friend class array2d_kernel_c;
public:
long nc (
) const { return data->nc(); }
const T& operator[] (
long column
) const;
T& operator[] (
long column
);
private:
typename array2d_base::row* data;
// restricted functions
row(){}
row(row&);
row& operator=(row&);
};
// -----------------------------------
array2d_kernel_c (
) :
rows(0)
{
}
virtual ~array2d_kernel_c (
) { clear(); }
long nc (
) const { return obj.nc(); }
long nr (
) const { return obj.nr(); }
row& operator[] (
long row
);
const row& operator[] (
long row
) const;
void swap (
array2d_kernel_c& item
)
{
exchange(obj,item.obj);
exchange(rows,item.rows);
}
void clear (
)
{
obj.clear();
if (rows != 0)
{
delete [] rows;
rows = 0;
}
}
void set_size (
long nr__,
long nc__
);
bool at_start (
) const { return obj.at_start();; }
void reset (
) const { obj.reset(); }
bool current_element_valid (
) const { return obj.current_element_valid(); }
const T& element (
) const;
T& element (
);
bool move_next (
) const { return obj.move_next(); }
unsigned long size (
) const { return obj.size(); }
private:
array2d_base obj;
row* rows;
};
template <
typename array2d_base
>
inline void swap (
array2d_kernel_c<array2d_base>& a,
array2d_kernel_c<array2d_base>& b
) { a.swap(b); }
template <
typename array2d_base
>
void serialize (
const array2d_kernel_c<array2d_base>& item,
std::ostream& out
)
{
try
{
serialize(item.nc(),out);
serialize(item.nr(),out);
item.reset();
while (item.move_next())
serialize(item.element(),out);
item.reset();
}
catch (serialization_error e)
{
throw serialization_error(e.info + "\n while serializing object of type array2d_kernel_c");
}
}
template <
typename array2d_base
>
void deserialize (
array2d_kernel_c<array2d_base>& item,
std::istream& in
)
{
try
{
long nc, nr;
deserialize(nc,in);
deserialize(nr,in);
item.set_size(nr,nc);
while (item.move_next())
deserialize(item.element(),in);
item.reset();
}
catch (serialization_error e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type array2d_kernel_c");
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename array2d_base
>
const typename array2d_base::type& array2d_kernel_c<array2d_base>::
element (
) const
{
// make sure requires clause is not broken
DLIB_CASSERT(current_element_valid() == true,
"\tT& array2d::element()()"
<< "\n\tYou can only call element() when you are at a valid one."
<< "\n\tthis: " << this
);
return obj.element();
}
// ----------------------------------------------------------------------------------------
template <
typename array2d_base
>
typename array2d_base::type& array2d_kernel_c<array2d_base>::
element (
)
{
// make sure requires clause is not broken
DLIB_CASSERT(current_element_valid() == true,
"\tT& array2d::element()()"
<< "\n\tYou can only call element() when you are at a valid one."
<< "\n\tthis: " << this
);
return obj.element();
}
// ----------------------------------------------------------------------------------------
template <
typename array2d_base
>
void array2d_kernel_c<array2d_base>::
set_size (
long nr_,
long nc_
)
{
// make sure requires clause is not broken
DLIB_CASSERT((nc_ > 0 && nr_ > 0) ||
(nc_ == 0 && nr_ == 0),
"\tvoid array2d::set_size(long nr_, long nc_)"
<< "\n\tYou have to give a non zero nc and nr or just make both zero."
<< "\n\tthis: " << this
<< "\n\tnc_: " << nc_
<< "\n\tnr_: " << nr_
);
obj.set_size(nr_,nc_);
// set up the rows array
if (rows != 0)
delete [] rows;
try
{
rows = new row[obj.nr()];
}
catch (...)
{
rows = 0;
obj.clear();
throw;
}
for (long i = 0; i < obj.nr(); ++i)
{
rows[i].data = &obj[i];
}
}
// ----------------------------------------------------------------------------------------
template <
typename array2d_base
>
typename array2d_kernel_c<array2d_base>::row& array2d_kernel_c<array2d_base>::
operator[] (
long row
)
{
// make sure requires clause is not broken
DLIB_CASSERT(row < nr() && row >= 0,
"\trow& array2d::operator[](long row)"
<< "\n\tThe row index given must be less than the number of rows."
<< "\n\tthis: " << this
<< "\n\trow: " << row
<< "\n\tnr(): " << nr()
);
return rows[row];
}
// ----------------------------------------------------------------------------------------
template <
typename array2d_base
>
const typename array2d_kernel_c<array2d_base>::row& array2d_kernel_c<array2d_base>::
operator[] (
long row
) const
{
// make sure requires clause is not broken
DLIB_CASSERT(row < nr() && row >= 0,
"\tconst row& array2d::operator[](long row) const"
<< "\n\tThe row index given must be less than the number of rows."
<< "\n\tthis: " << this
<< "\n\trow: " << row
<< "\n\tnr(): " << nr()
);
return rows[row];
}
// ----------------------------------------------------------------------------------------
template <
typename array2d_base
>
const typename array2d_base::type& array2d_kernel_c<array2d_base>::row::
operator[] (
long column
) const
{
// make sure requires clause is not broken
DLIB_CASSERT(column < nc() && column >= 0,
"\tconst T& array2d::operator[](long column) const"
<< "\n\tThe column index given must be less than the number of columns."
<< "\n\tthis: " << this
<< "\n\tcolumn: " << column
<< "\n\tnc(): " << nc()
);
return (*data)[column];
}
// ----------------------------------------------------------------------------------------
template <
typename array2d_base
>
typename array2d_base::type& array2d_kernel_c<array2d_base>::row::
operator[] (
long column
)
{
// make sure requires clause is not broken
DLIB_CASSERT(column < nc() && column >= 0,
"\tT& array2d::operator[](long column)"
<< "\n\tThe column index given must be less than the number of columns."
<< "\n\tthis: " << this
<< "\n\tcolumn: " << column
<< "\n\tnc(): " << nc()
);
return (*data)[column];
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ARRAY2D_KERNEl_C_