From 772f75582bf22b1cfe662fa42637e16718e79ca8 Mon Sep 17 00:00:00 2001
From: Luc Hermitte <luc.hermitte@c-s.fr>
Date: Fri, 20 Apr 2012 21:03:02 +0200
Subject: [PATCH] ENH: OTB-134/OGR: print-self -> MPL based experiment to print
 field values

---
 .../OGRAdapters/otbOGRFeatureWrapper.cxx      |  20 +-
 .../OGRAdapters/otbOGRFeatureWrapper.h        |   6 +-
 .../OGRAdapters/otbOGRFieldWrapper.h          | 247 ++++++++++++++++++
 .../OGRAdapters/otbOGRLayerWrapper.cxx        |   1 +
 4 files changed, 269 insertions(+), 5 deletions(-)
 create mode 100644 Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.h

diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.cxx b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.cxx
index 8b2d5aa57a..5216555995 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.cxx
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.cxx
@@ -24,6 +24,7 @@
 #include <boost/make_shared.hpp>
 #include "ogr_feature.h"
 
+#include "otbOGRFieldWrapper.h"
 /*===========================================================================*/
 /*======================[ Construction / Destruction ]=======================*/
 /*===========================================================================*/
@@ -66,10 +67,19 @@ void otb::ogr::Feature::PrintSelf(std::ostream & os, itk::Indent indent) const
   os << indent << "+";
   os << " " << nbFields << " fields\n";
   for (int i=0; i!=nbFields; ++i) {
-    OGRFieldDefn & field = *const_cast<Feature*>(this)->ogr().GetFieldDefnRef(i);
+    assert(ogr().GetFieldDefnRef(i));
+    Field     field(*this, i);
     os << indent << "|" << one_indent << "+ ";
-    os << field.GetNameRef() << ": ";
-    os << "(" << OGRFieldDefn::GetFieldTypeName(field.GetType()) << ")";
+    os << field.GetName() << ": ";
+    switch (field.GetType())
+      {
+      case OFTInteger: os << field.GetValue<int>(); break;
+      case OFTReal   : os << field.GetValue<double>(); break;
+    case OFTString : os << field.GetValue<std::string>();
+      break;
+    default: os << "??? -> " << field.GetType(); break;
+      }
+    os << " (" << OGRFieldDefn::GetFieldTypeName(field.GetType()) << ")";
     os << "\n";
   }
 }
@@ -87,3 +97,7 @@ bool otb::ogr::operator==(otb::ogr::Feature const& lhs, otb::ogr::Feature const&
     (l && r && l->Equal(r)) // must be non-null to compare them with Equal
 ;
 }
+
+size_t otb::ogr::Feature::GetSize() const {
+  return ogr().GetFieldCount();
+}
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.h b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.h
index f035997065..c959ee65b6 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.h
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.h
@@ -47,8 +47,8 @@ public:
   Feature clone() const;
   void PrintSelf(std::ostream &os, itk::Indent indent) const;
 
-  OGRFeature const& ogr() const
-    {
+  OGRFeature & ogr() const
+    { // not returning a OGRFeature const& because OGR is not const-correct
     CheckInvariants();
     return *m_Feature;
     }
@@ -58,6 +58,8 @@ public:
     return *m_Feature;
     }
 
+  size_t GetSize() const;
+
   friend bool otb::ogr::operator==(Feature const& lhs, Feature const& rhs);
 private:
   void CheckInvariants() const
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.h b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.h
new file mode 100644
index 0000000000..9625f8be36
--- /dev/null
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.h
@@ -0,0 +1,247 @@
+/*=========================================================================
+
+  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_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/mpl/assert.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+// class OGRFeature;
+#include "ogr_feature.h"
+class OGRFieldDefn;
+
+
+
+
+#include <iomanip>
+template <typename RT, typename CT> void print_adress(RT (CT::*p)(int))
+{
+  unsigned char const * first = reinterpret_cast<unsigned char *>(&p);
+  unsigned char const * last = reinterpret_cast<unsigned char *>(&p + 1);
+
+  for (; first != last; ++first)
+    {
+    std::cout << std::hex << std::setw(2) << std::setfill('0')
+      << (int)*first << ' ';
+    }
+  std::cout << "\n";
+}
+
+
+namespace types_ { // Anonymous namespace
+using namespace boost::mpl;
+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> >
+  > FieldType_Map;
+
+template
+  < typename T
+  , T ( OGRFeature::*ptr_to_function )(int)
+  , typename FinalReturnType = T
+  > class member_function_get_ptr
+    {
+  public:
+    static FinalReturnType call(OGRFeature &f, int index)
+      {
+      // print_adress(ptr_to_function);
+      // print_adress(&OGRFeature::GetFieldAsString);
+      return (f.*ptr_to_function)(index);
+      }
+    };
+
+typedef map
+  < pair<int_<OFTInteger>, member_function_get_ptr<int,         &OGRFeature::GetFieldAsInteger> >
+  , pair<int_<OFTReal>,    member_function_get_ptr<double,      &OGRFeature::GetFieldAsDouble> >
+  , pair<int_<OFTString>,  member_function_get_ptr<char const*, &OGRFeature::GetFieldAsString, std::string> >
+  > FieldGetters_Map;
+
+BOOST_STATIC_ASSERT(!(boost::is_same<
+  member_function_get_ptr<int,         &OGRFeature::GetFieldAsInteger>,
+  member_function_get_ptr<double,      &OGRFeature::GetFieldAsDouble>
+  >::value
+  ));
+
+BOOST_STATIC_ASSERT(!(boost::is_same< int, float >::value));
+BOOST_STATIC_ASSERT(!(boost::is_same<
+  int_<OFTReal  >::type,
+  int_<OFTString>::type
+  >::value
+  ));
+BOOST_STATIC_ASSERT(!(boost::is_same<
+  at<FieldType_Map,  float>,
+  void_
+  >::value
+  ));
+BOOST_STATIC_ASSERT(!(boost::is_same<
+  at<FieldType_Map,  double>,
+  int_<OFTReal>
+  >::value
+  ));
+BOOST_STATIC_ASSERT(!(boost::is_same<
+  at<FieldType_Map,  double >::type,
+  at<FieldType_Map,  int >::type
+  >::value
+  ));
+BOOST_STATIC_ASSERT((
+  at<FieldType_Map,  double>::type::value !=
+  at<FieldType_Map,  int   >::type::value
+  ));
+BOOST_STATIC_ASSERT(!(boost::is_same<
+  at<FieldGetters_Map, int_<OFTReal> >,
+  at<FieldGetters_Map, int_<OFTString> >
+  >::value
+  ));
+} // Anonymous namespace
+
+namespace otb { namespace ogr {
+class FieldDefn
+  {
+public:
+  FieldDefn(OGRFieldDefn& definition) : m_definition(&definition){ }
+  std::string  GetName() const
+    {
+    assert(m_definition);
+    return m_definition->GetNameRef();
+    }
+  OGRFieldType GetType() const
+    {
+    assert(m_definition);
+    return m_definition->GetType();
+    }
+
+private:
+  OGRFieldDefn * m_definition;
+  };
+
+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, int index)
+    {
+    return f.GetFieldAsInteger(index);
+    }
+  };
+
+template <> struct FieldDecodingTraitsGetter<double>
+  {
+  typedef double Type;
+  static Type Get(OGRFeature &f, int index)
+    {
+    return f.GetFieldAsDouble(index);
+    }
+  };
+
+template <> struct FieldDecodingTraitsGetter<std::string>
+  {
+  typedef std::string Type;
+  static Type Get(OGRFeature &f, int index)
+    {
+    return f.GetFieldAsString(index);
+    }
+  };
+
+/*===========================================================================*/
+/*=================================[ Field ]=================================*/
+/*===========================================================================*/
+class Field
+  {
+public:
+  Field(Feature const& feature, int index)
+    :   m_Definition(*feature.ogr().GetFieldDefnRef(index))
+      , m_Feature(feature)
+      , m_index(index)
+  {
+  assert(feature.ogr().GetFieldDefnRef(index));
+  }
+  // Field(OGRFeature& field, FieldDefn const& definition);
+  FieldDefn const& GetDefinition() const;
+  OGRFieldType GetType() const
+    { return m_Definition.GetType(); }
+  std::string GetName() const
+    { return m_Definition.GetName(); }
+
+#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);
+    }
+#endif
+  template <typename T> T GetValue() const
+    {
+    const int VALUE = boost::mpl::at<types_::FieldType_Map, T>::type::value;
+    typedef typename boost::mpl::at<types_::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< types_::FieldGetters_Map, Kind >::type function_;
+    BOOST_STATIC_ASSERT(!(boost::is_same< function_, boost::mpl::void_ >::value));
+    assert(m_index >= 0 && m_index < m_Feature.GetSize());
+    return function_::call(m_Feature.ogr(), m_index);
+    // return FieldDecodingTraitsGetter<T>::Get(m_Feature.ogr(), m_index);
+    }
+#if 0
+  std::ostream & PrintSelf(std::ostream&os, itk::Indent indent) {
+    os << indent;
+    switch (GetType)
+      {
+machin_int:
+      os << GetValue<int>();
+      break;
+    default:
+
+      }
+    return os;
+  }
+#endif
+private:
+  FieldDefn  m_Definition;
+  Feature    m_Feature;
+  int        m_index; // all the fields decoding is at the wrong place (OGRFeature instead of OGRField)
+  };
+
+} } // end namespace otb::ogr
+
+#ifndef OTB_MANUAL_INSTANTIATION
+// #include "otbOGRFieldWrapper.txx"
+#endif
+
+#endif // __otbOGRFieldWrapper_h
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.cxx b/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.cxx
index 288dfd4129..92434357fc 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.cxx
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.cxx
@@ -20,6 +20,7 @@
 /*===============================[ Includes ]================================*/
 /*===========================================================================*/
 #include "otbOGRLayerWrapper.h"
+
 #include <cassert>
 #include <boost/bind.hpp>
 #include <boost/foreach.hpp>
-- 
GitLab