From 812e9d94602e5a6b8fcc124c99457c9f1b8715cc Mon Sep 17 00:00:00 2001
From: Luc Hermitte <luc.hermitte@c-s.fr>
Date: Thu, 31 May 2012 18:51:35 +0200
Subject: [PATCH] ENH: OTB-134/OGR -> + Field copy

---
 .../OGRAdapters/otbOGRFieldWrapper.cxx        | 13 ++++++++
 .../OGRAdapters/otbOGRFieldWrapper.h          | 30 +++++++++++++++++++
 .../OGRAdapters/otbOGRFieldWrapper.txx        | 25 ++++++++++++++++
 3 files changed, 68 insertions(+)

diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.cxx b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.cxx
index eee8ee907d..15def7ef1b 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.cxx
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.cxx
@@ -159,3 +159,16 @@ void otb::ogr::Field::UncheckedUnset() const
 {
   m_Feature->UnsetField(m_index);
 }
+
+void otb::ogr::Field::UncheckedAssign(Field const& f)
+{
+  if (f.HasBeenSet())
+    {
+    OGRField & of = f.ogr();
+    m_Feature->SetField(m_index, &of); // OGR API copies *of
+    }
+  else // not sure OGR setField handle the case where new fields are unset
+    {
+    this->Unset();
+    }
+}
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.h b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.h
index c80bce4d7a..8bcea06287 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.h
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.h
@@ -77,6 +77,10 @@ class Feature;
  * Instances of \c Field are expected to be built from an existing \c Feature
  * with which they'll share their owning \c OGRFeature.
  *
+ * A \c Field instance works as a proxy. Copying a field will only have it share
+ * the actual \c OGRField between several instances. In order to copy a field
+ * value from another field, use \c Field::assign().
+ *
  * \invariant <tt>m_Feature</tt> shall be valid (i.e. not wrapping a null \c
  * OGRFeature).
  * \invariant <tt>m_index < m_Feature->GetFieldCount()</tt>.
@@ -133,6 +137,31 @@ public:
 
   /** Prints self into stream. */
   std::ostream & PrintSelf(std::ostream&os, itk::Indent indent) const;
+
+  /** Copies a field.
+   * As \c Field is a proxy type, this function is the only possible way to copy a field.
+   *
+   * First, the field must be defined with a definition, then it could be set
+   * from another field value.
+   * \code
+   * Field srcField = srcFeature[42];
+   * Feature dstFeature(layerDefinition);
+   * Field dst(dstFeature, 12);
+   * dstField.Assign(srcField);
+   * \endcode
+   */
+  void Assign(Field const& f);
+
+  /** Access to the raw underlying OGR data.
+   * This function provides an abstraction leak in case deeper control on the
+   * underlying \c OGRFeature is required.
+   * \warning You must under no circonstance try to delete the \c OGRField
+   * obtained this way.
+   */
+  OGRField & ogr() const;
+
+  /** \copydoc Field::ogr() const */
+  OGRField & ogr();
 private:
   /**\name Unchecked definitions
    * All the definitions that follow do the real work. However, they are not the
@@ -145,6 +174,7 @@ private:
   bool           UncheckedHasBeenSet() const;
   void           UncheckedUnset() const;
   std::ostream & UncheckedPrintSelf(std::ostream&os, itk::Indent indent) const;
+  void           UncheckedAssign(Field const& f);
   //@}
 
   /**
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.txx b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.txx
index 75c73fbb94..d519b21a90 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.txx
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.txx
@@ -439,4 +439,29 @@ void otb::ogr::Field::Unset() const
   UncheckedUnset();
 }
 
+inline
+void otb::ogr::Field::Assign(Field const& f)
+{
+  CheckInvariants();
+  f.CheckInvariants();
+  assert(f.GetDefinition() == this->GetDefinition() && "Cannot assign from a field that doesn't have the same definition");
+  UncheckedAssign(f);
+  CheckInvariants();
+}
+
+inline
+OGRField & otb::ogr::Field::ogr() const
+{
+  return const_cast <Field*>(this)->ogr();
+}
+
+inline
+OGRField & otb::ogr::Field::ogr()
+{
+  CheckInvariants();
+  OGRField * f = m_Feature->GetRawFieldRef(m_index);
+  assert(f && "The field obtained shall not be null");
+  return *f;
+}
+
 #endif // __otbOGRFieldWrapper_txx
-- 
GitLab