Commit 20a5cc18 authored by Luc Hermitte's avatar Luc Hermitte

DOC: OTB-134/OGR -> field

parent 62169541
......@@ -82,6 +82,10 @@ void otb::ogr::DataSource::Reset(OGRDataSource * source)
}
namespace { // Anonymous namespace
/**\ingroup GeometryInternals
* \brief Type for associating filename extension with OGR driver names.
* \since OTB v 3.14.0
*/
struct ExtensionDriverAssociation
{
char const* extension;
......@@ -91,6 +95,10 @@ struct ExtensionDriverAssociation
return ext == extension;
}
};
/**\ingroup GeometryInternals
* \brief Associative table of filename extension -> OGR driver names.
* \since OTB v 3.14.0
*/
const ExtensionDriverAssociation k_ExtensionDriverMap[] =
{
{"SHP", "ESRI Shapefile"},
......@@ -100,6 +108,14 @@ const ExtensionDriverAssociation k_ExtensionDriverMap[] =
{"SQLITE", "SQLite"},
{"KML", "KML"},
};
/**\ingroup GeometryInternals
* \brief Returns the OGR driver name associated to a filename.
* \since OTB v 3.14.0
* \note Relies on the driver name associated to the filename extension in \c
* k_ExtensionDriverMap.
* \note As a special case, filenames starting with "PG:" are bound to
* "PostgreSQL".
*/
char const* DeduceDriverName(std::string filename)
{
std::transform(filename.begin(), filename.end(), filename.begin(), (int (*)(int))toupper);
......@@ -168,7 +184,8 @@ otb::ogr::DataSource::New(std::string const& filename, Modes::type mode)
char const* driverName = DeduceDriverName(filename);
if (!driverName)
{
itkGenericExceptionMacro(<< "No OGR driver known to OTB to create and handle a DataSource named <"<<filename<<">.");
itkGenericExceptionMacro(<< "No OGR driver known to OTB to create and handle a DataSource named <"
<<filename<<">.");
}
OGRSFDriver * d = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driverName);
......@@ -354,18 +371,22 @@ otb::ogr::Layer otb::ogr::DataSource::ExecuteSQL(
/*===============================[ features ]================================*/
/*===========================================================================*/
namespace { // Anonymous namespace
struct AccuLayersSizes
/**\ingroup GeometryInternals
* \brief %Functor used to accumulate the sizes of the layers in a \c DataSource.
* \since OTB v 3.14.0
*/
struct AccuLayersSizes
{
AccuLayersSizes(bool doForceComputation)
: m_doForceComputation(doForceComputation) { }
int operator()(int accumulated, otb::ogr::Layer const& layer) const
{
AccuLayersSizes(bool doForceComputation)
: m_doForceComputation(doForceComputation) { }
int operator()(int accumulated, otb::ogr::Layer const& layer) const
{
const int loc_size = layer.GetFeatureCount(m_doForceComputation);
return loc_size < 0 ? loc_size : loc_size+accumulated;
}
private:
bool m_doForceComputation;
};
const int loc_size = layer.GetFeatureCount(m_doForceComputation);
return loc_size < 0 ? loc_size : loc_size+accumulated;
}
private:
bool m_doForceComputation;
};
} // Anonymous namespace
int otb::ogr::DataSource::Size(bool doForceComputation) const
......
......@@ -29,7 +29,7 @@
/*===========================[ Static Assertions ]===========================*/
/*===========================================================================*/
namespace otb { namespace ogr {
namespace metaprog {
namespace internal {
BOOST_STATIC_ASSERT(!(boost::is_same<
MemberGetterPtr<int, &OGRFeature::GetFieldAsInteger>,
MemberGetterPtr<double, &OGRFeature::GetFieldAsDouble>
......@@ -84,13 +84,13 @@ BOOST_STATIC_ASSERT((boost::is_contiguous<std::vector<int> >::value));
std::string otb::ogr::FieldDefn::GetName() const
{
assert(m_definition);
assert(m_definition && "No field definition wrapped");
return m_definition->GetNameRef();
}
OGRFieldType otb::ogr::FieldDefn::GetType() const
{
assert(m_definition);
assert(m_definition && "No field definition wrapped");
return m_definition->GetType();
}
......@@ -103,13 +103,13 @@ otb::ogr::Field::Field(otb::ogr::Feature & feature, size_t index)
, m_Feature(feature.sptr())
, m_index(index)
{
assert(m_Feature);
assert(m_Feature->GetFieldDefnRef(index));
CheckInvariants();
}
std::ostream & otb::ogr::Field::PrintSelf(
std::ostream& os, itk::Indent indent) const
{
CheckInvariants();
const itk::Indent one_indent = itk::Indent().GetNextIndent();
// os << indent << "|" << one_indent << "+ ";
os << indent << this->GetName() << ": ";
......@@ -143,12 +143,12 @@ std::ostream & otb::ogr::Field::PrintSelf(
bool otb::ogr::Field::HasBeenSet() const
{
assert(m_Feature);
CheckInvariants();
return m_Feature->IsFieldSet(m_index);
}
void otb::ogr::Field::Unset() const
{
assert(m_Feature);
CheckInvariants();
m_Feature->UnsetField(m_index);
}
......@@ -18,241 +18,22 @@
#ifndef __otbOGRFieldWrapper_h
#define __otbOGRFieldWrapper_h
#include <vector>
#include <string>
#include <boost/mpl/map.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/at.hpp>
#include <boost/static_assert.hpp>
#include <boost/range/size.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/shared_ptr.hpp>
class OGRFieldDefn;
// class OGRFeature;
#include "ogr_feature.h" // OGRFeature::*field_getters
class OGRFeature;
#include "ogr_core.h" // OGR enums
#include "itkIndent.h"
#include <cassert>
#include "boost/type_traits/is_contiguous.h" // from OTB actually
namespace otb { namespace ogr {
/**\ingroup Geometry
* \defgroup GeometryInternals Geometry Internals
* \since OTB v 3.14.0
*/
/**\ingroup GeometryInternals
* Namespace used to host internal meta-prog definitions.
* \since OTB v 3.14.0
*/
namespace metaprog { // namespace metaprog
using namespace boost::mpl;
/**\ingroup GeometryInternals
* Associative map of C++ types to OGR field types (\c OGRFieldType).
* \internal Relies on Boost.MPL
* \since OTB v 3.14.0
*/
typedef boost::mpl::map
< pair<int, int_<OFTInteger> >
, pair<std::vector<int>, int_<OFTIntegerList> >
, pair<double, int_<OFTReal> >
, pair<std::vector<double>, int_<OFTRealList> >
, pair<std::string, int_<OFTString> >
, pair<std::vector<std::string>, int_<OFTStringList> >
// OFTBinary
// OFTDate
// OFTTime
// OFTDateTime
> FieldType_Map;
/**\ingroup GeometryInternals
* \class MemberGetterPtr
* Type for hosting simple member-function pointers to field getters.
* \tparam T type of field according to OGR API.
* \tparam ptr_to_function member function pointer to a field getter from \c
* OGRFeature.
* \tparam FinalReturnType type of the field according to OTB wrappers (default
* <tt> = T</tt>)
*
* \internal
* This is a hack to pass a member function pointer as template-parameter.
* \since OTB v 3.14.0
*/
template
< typename T
, T ( OGRFeature::*ptr_to_function )(int)
, typename FinalReturnType = T
> class MemberGetterPtr
{
public:
static FinalReturnType call(OGRFeature &f, int index)
{
return (f.*ptr_to_function)(index);
}
};
/**\ingroup GeometryInternals
* \class MemberSetterPtr
* Type for hosting simple member-function pointers to field setters.
* \tparam T type of field according to OGR API.
* \tparam ptr_to_function member function pointer to a field setter from \c
* OGRFeature.
* <tt> = T</tt>)
*
* \internal
* This is a hack to pass a member function pointer as template-parameter.
* \since OTB v 3.14.0
*/
template
< typename T
, void ( OGRFeature::*ptr_to_function )(int, T value)
> class MemberSetterPtr
{
public:
static void call(OGRFeature &f, int index, T const& value)
{
(f.*ptr_to_function)(index, value);
}
};
/**\ingroup GeometryInternals
* \class MemberContainerGetterPtr
* Type for hosting simple member-function pointers to list-field getters.
* \tparam T type of field according to OGR API.
* \tparam ptr_to_function member function pointer to a list-field getter from
* \c OGRFeature.
* \tparam FinalReturnType type of the list-field according to OTB wrappers
* (default <tt> = std::vector<T></tt>)
*
* \internal
* This is a hack to pass a member function pointer as template-parameter.
* \since OTB v 3.14.0
*/
template
< typename T
, T const* ( OGRFeature::*ptr_to_function )(int, int*)
, typename FinalReturnType = std::vector<T>
> class MemberContainerGetterPtr
{
public:
static FinalReturnType call(OGRFeature &f, int index)
{
int nb = 0;
T const* raw_container = (f.*ptr_to_function)(index, &nb);
const FinalReturnType res(raw_container+0, raw_container+nb);
return res;
}
};
/*===========================================================================*/
template
< typename T
, void ( OGRFeature::*ptr_to_function )(int, int, T*) // not const-correct
, typename ActualParamType = std::vector<T>
, bool Is_contiguous = boost::is_contiguous<ActualParamType>::value
> class TagDispatchMemberContainerSetterPtr;
template
< typename T
, void ( OGRFeature::*ptr_to_function )(int, int, T*) // not const-correct
, typename ActualParamType
> class TagDispatchMemberContainerSetterPtr<T, ptr_to_function, ActualParamType, true>
{
public:
static void call(OGRFeature &f, int index, ActualParamType const& container)
{
const int nb = boost::size(container);
(f.*ptr_to_function)(index, nb, &container[0]);
}
};
template
< typename T
, void ( OGRFeature::*ptr_to_function )(int, int, T*) // not const-correct
, typename ActualParamType
> class TagDispatchMemberContainerSetterPtr<T, ptr_to_function, ActualParamType, false>
{
public:
static void call(OGRFeature &f, int index, ActualParamType const& container)
{
const int nb = boost::size(container);
std::vector<T> v(boost::begin(container), boost::end(container));
(f.*ptr_to_function)(index, nb, &v[0]);
}
};
/**\ingroup GeometryInternals
* \class MemberContainerSetterPtr
* Type for hosting simple member-function pointers to list-field setters.
* \tparam T type of field according to OGR API.
* \tparam ptr_to_function member function pointer to a list-field setter from
* \c OGRFeature.
* \tparam FinalReturnType type of the list-field according to OTB wrappers
* (default <tt> = std::vector<T></tt>)
*
* \internal
* This is a hack to pass a member function pointer as template-parameter.
* \since OTB v 3.14.0
*/
template
< typename T
, void ( OGRFeature::*ptr_to_function )(int, int, T*) // not const-correct
, typename ActualParamType = std::vector<T>
> class MemberContainerSetterPtr
{
public:
static void call(OGRFeature &f, int index, ActualParamType const& container)
{
TagDispatchMemberContainerSetterPtr<
T
,ptr_to_function
,ActualParamType
, boost::is_contiguous<ActualParamType>::value
>::call(f, index, container);
}
};
/**\ingroup GeometryInternals
* Associative map of OGR field types (\c OGRFieldType) to their associated
* getters.
* \internal Relies on Boost.MPL
* \since OTB v 3.14.0
*/
typedef map
< pair<int_<OFTInteger>, MemberGetterPtr<int, &OGRFeature::GetFieldAsInteger> >
, pair<int_<OFTIntegerList>, MemberContainerGetterPtr<int, &OGRFeature::GetFieldAsIntegerList> >
, pair<int_<OFTReal>, MemberGetterPtr<double, &OGRFeature::GetFieldAsDouble> >
, pair<int_<OFTRealList>, MemberContainerGetterPtr<double, &OGRFeature::GetFieldAsDoubleList> >
, pair<int_<OFTString>, MemberGetterPtr<char const*, &OGRFeature::GetFieldAsString, std::string> >
// , pair<int_<OFTStringList>, MemberGetterPtr<char const*, &OGRFeature::GetFieldAsString, std::string> >
> FieldGetters_Map;
/**\ingroup GeometryInternals
* Associative map of OGR field types (\c OGRFieldType) to their associated
* setters.
* \internal Relies on Boost.MPL
* \since OTB v 3.14.0
*/
typedef map
< pair<int_<OFTInteger>, MemberSetterPtr<int, &OGRFeature::SetField> >
, pair<int_<OFTIntegerList>, MemberContainerSetterPtr<int, &OGRFeature::SetField> >
, pair<int_<OFTReal>, MemberSetterPtr<double, &OGRFeature::SetField> >
, pair<int_<OFTRealList>, MemberContainerSetterPtr<double, &OGRFeature::SetField> >
// , pair<int_<OFTString>, MemberSetterPtr<char const*, &OGRFeature::SetField, std::string> >
// , pair<int_<OFTStringList>, MemberSetterPtr<char const*, &OGRFeature::GetFieldAsString, std::string> >
> FieldSetters_Map;
} // namespace metaprog
/*===========================[ Field definition ]============================*/
/*===========================================================================*/
/**\ingroup Geometry
* \class FieldDefn
* \brief Encapsulation of \c OGRFieldDefn
* \brief Encapsulation of \c OGRFieldDefn: field definition.
* \invariant <tt>m_definition != 0</tt>
* \invariant \c m_definition lifetime is of the responsability of the owning \c
* \c OGRFeatureDefn.
......@@ -263,52 +44,16 @@ class FieldDefn
{
public:
FieldDefn(OGRFieldDefn& definition) : m_definition(&definition){ }
std::string GetName() const;
OGRFieldType GetType() const;
std::string GetName() const; //!< Field name accessor.
OGRFieldType GetType() const; //!< Field type accessor.
private:
OGRFieldDefn * m_definition; // pointer in order to support assignments
/**Pointer to the actual definition.
* \internal pointer in order to support assignments
*/
OGRFieldDefn * m_definition;
};
#if 0
template <typename FieldType> struct FieldDecodingTraitsGetter {};
template <typename FieldType> struct FieldDecodingTraits
{
// good for int, double, char const*, list of strings
typedef FieldType Type;
static void Set(OGRFeature &f, int index, Type const& value)
{
f.SetField(index, value);
}
};
template <> struct FieldDecodingTraitsGetter<int>
{
typedef int Type;
static Type Get(OGRFeature &f, size_t index)
{
return f.GetFieldAsInteger(index);
}
};
template <> struct FieldDecodingTraitsGetter<double>
{
typedef double Type;
static Type Get(OGRFeature &f, size_t index)
{
return f.GetFieldAsDouble(index);
}
};
template <> struct FieldDecodingTraitsGetter<std::string>
{
typedef std::string Type;
static Type Get(OGRFeature &f, size_t index)
{
return f.GetFieldAsString(index);
}
};
#endif
/*===========================================================================*/
/*=================================[ Field ]=================================*/
......@@ -320,67 +65,90 @@ class Feature;
* \brief Encapsulation of \c OGRField
* Instances of \c Field are expected to be built from an existing \c Feature
* with which they'll share their owning \c OGRFeature.
*
* \invariant <tt>m_Feature</tt> shall be valid (i.e. not wrapping a null \c
* OGRFeature).
* \invariant <tt>m_index < m_Feature->GetFieldCount()</tt>.
* \invariant <tt>m_Feature->GetFieldDefnRef(m_index) != 0</tt>.
* \sa OGRField
* \since OTB v 3.14.0
*/
class Field
{
{
public:
/**
* Constructor.
* \param[in,out] feature \c Feature from which the field is.
* \param[in] index Index of the field in the \c Feature.
* \throw None
*/
Field(Feature & feature, size_t index);
// Field(OGRFeature& field, FieldDefn const& definition);
/// %Field definition accessor.
FieldDefn const& GetDefinition() const;
/// %Field type accessor.
OGRFieldType GetType() const
{ return m_Definition.GetType(); }
/// %Field name accessor.
std::string GetName() const
{ return m_Definition.GetName(); }
/// Tells whether the field value has been set.
bool HasBeenSet() const;
/// Unsets the value of the field.
void Unset() const;
#if 0
template <typename T> void SetValue(T const& v)
{
assert(m_Definition.GetType() == FieldTraits<T>::kind);
FieldDecodingTraits<T>::Set(m_Feature.ogr(), m_index, v);
}
#else
template <typename T> void SetValue(T const& value)
{
const int VALUE = boost::mpl::at<metaprog::FieldType_Map, T>::type::value;
typedef typename boost::mpl::at<metaprog::FieldType_Map, T>::type Kind;
BOOST_STATIC_ASSERT(!(boost::is_same<Kind, boost::mpl::void_>::value));
assert(m_Definition.GetType() == Kind::value);
typedef typename boost::mpl::at<metaprog::FieldSetters_Map, Kind>::type SetterType;
BOOST_STATIC_ASSERT(!(boost::is_same<SetterType, boost::mpl::void_>::value));
assert(m_index >= 0 && int(m_index) < m_Feature->GetFieldCount());
SetterType::call(*m_Feature, m_index, value);
}
#endif
template <typename T> T GetValue() const
{
const int VALUE = boost::mpl::at<metaprog::FieldType_Map, T>::type::value;
typedef typename boost::mpl::at<metaprog::FieldType_Map, T>::type Kind;
BOOST_STATIC_ASSERT(!(boost::is_same<Kind, boost::mpl::void_>::value));
assert(m_Definition.GetType() == Kind::value);
typedef typename boost::mpl::at<metaprog::FieldGetters_Map, Kind>::type GetterType;
BOOST_STATIC_ASSERT(!(boost::is_same<GetterType, boost::mpl::void_>::value));
assert(m_index >= 0 && int(m_index) < m_Feature->GetFieldCount());
return GetterType::call(*m_Feature, m_index);
}
/**
* Value setter.
* \param[in] value New value for the field.
* \throw None
* \pre \c value's kind must match the field's type.
* \internal
* This function automagically decodes the type of the parameter in order to
* use the ad'hoc setter from \c OGRFeature.
*/
template <typename T> void SetValue(T const& value);
/**
* Value getter.
* \tparam T expected type for the stored value.
* \throw None
* \pre \c T must match the field's type.
* \pre The field must have set.
* \internal
* This function automagically deduce the ad'hoc getter (from \c OGRFeature)
* from \c T.
*/
template <typename T> T GetValue() const;
/** Prints self into stream. */
std::ostream & PrintSelf(std::ostream&os, itk::Indent indent) const;
private:
/**
* Internal function to check class invariants.
* If any invariant is broken, an assertion ill be fired.
* \internal
* This function is defined inlined in order to be able to inhibit invariants
* checking depending on the compilation mode (on \c NDEBUG preprocessor
* define actually).
*/
void CheckInvariants() const;
/// Definition of the field.
FieldDefn m_Definition;
/// Link to the actual \c OGRFeature in charge of the fields.
boost::shared_ptr<OGRFeature> & m_Feature;
// all the fields decoding is at the wrong place (OGRFeature instead of
// OGRField) => need for an index
/** Index of the field according to the feature definition.
* \internal
* All the fields decoding is at the wrong place (\c OGRFeature instead of
* \c OGRField) => need for an index.
*/
size_t m_index;
};
};
} } // end namespace otb::ogr
#ifndef OTB_MANUAL_INSTANTIATION
// #include "otbOGRFieldWrapper.txx"
#include "otbOGRFieldWrapper.txx"
#endif
#endif // __otbOGRFieldWrapper_h
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef __otbOGRFieldWrapper_txx
#define __otbOGRFieldWrapper_txx
/*===========================================================================*/
/*===============================[ Includes ]================================*/
/*===========================================================================*/
#include "otbOGRFieldWrapper.h"
#include <cassert>
#include <vector>
#include <boost/mpl/map.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/at.hpp>
#include <boost/static_assert.hpp>
#include <boost/range/size.hpp>
#include <boost/type_traits/is_same.hpp>
#include "boost/type_traits/is_contiguous.h" // from OTB actually
#include "ogr_feature.h" // OGRFeature::*field_getters
/*===========================================================================*/
/*================[ Associations C++ types -> OGR functions ]================*/
/*===========================================================================*/
namespace otb { namespace ogr {
/**\ingroup Geometry
* \defgroup GeometryInternals Geometry Internals
* \since OTB v 3.14.0
*/
/**\ingroup GeometryInternals
* Namespace used to host internal meta-prog definitions.
* \since OTB v 3.14.0
*/
namespace internal { // namespace internal
using namespace boost::mpl;
/**\ingroup GeometryInternals