OTB  9.0.0
Orfeo Toolbox
otbOGRFieldWrapper.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 
22 #ifndef otbOGRFieldWrapper_hxx
23 #define otbOGRFieldWrapper_hxx
24 
25 /*===========================================================================*/
26 /*===============================[ Includes ]================================*/
27 /*===========================================================================*/
28 #include "otbOGRFieldWrapper.h"
29 #include "otbConfigure.h"
30 #include <cassert>
31 #include <vector>
32 #include <boost/mpl/map.hpp>
33 #include <boost/mpl/vector.hpp>
34 #include <boost/mpl/pair.hpp>
35 #include <boost/mpl/int.hpp>
36 #include <boost/mpl/at.hpp>
37 #include <boost/mpl/assert.hpp>
38 // #include <boost/mpl/print.hpp>
39 
40 #include <boost/static_assert.hpp>
41 #if defined(__GNUC__) || defined(__clang__)
42 #pragma GCC diagnostic push
43 #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
44 #include <boost/range/size.hpp>
45 #pragma GCC diagnostic pop
46 #else
47 #include <boost/range/size.hpp>
48 #endif
49 
50 #include <boost/type_traits/is_same.hpp>
51 // #include "boost/type_traits/is_array.hpp"
52 #include "boost/type_traits/is_contiguous.h" // from OTB actually
53 
54 #if defined(__GNUC__) || defined(__clang__)
55 #pragma GCC diagnostic push
56 #pragma GCC diagnostic ignored "-Wshadow"
57 #include "ogr_feature.h" // OGRFeature::*field_getters
58 #pragma GCC diagnostic pop
59 #else
60 #include "ogr_feature.h" // OGRFeature::*field_getters
61 #endif
62 #include "cpl_string.h" // CSLCount
63 #include "otbOGRHelpers.h"
64 
65 
66 /*===========================================================================*/
67 /*================[ Associations C++ types -> OGR functions ]================*/
68 /*===========================================================================*/
69 
70 namespace otb
71 {
72 namespace ogr
73 {
83 namespace internal
84 { // namespace internal
85 namespace mpl = boost::mpl;
86 
94 typedef mpl::map<mpl::pair<int, mpl::int_<OFTInteger>>, mpl::pair<std::vector<int>, mpl::int_<OFTIntegerList>>, mpl::pair<double, mpl::int_<OFTReal>>,
95  mpl::pair<std::vector<double>, mpl::int_<OFTRealList>>, mpl::pair<std::string, mpl::int_<OFTString>>, mpl::pair<char*, mpl::int_<OFTString>>,
96  mpl::pair<char const*, mpl::int_<OFTString>>, mpl::pair<std::vector<std::string>, mpl::int_<OFTStringList>>,
97  mpl::pair<GIntBig, mpl::int_<OFTInteger64>>, mpl::pair<std::vector<GIntBig>, mpl::int_<OFTInteger64List>>
98 
99  // OFTBinary
100  // OFTDate
101  // OFTTime
102  // OFTDateTime
103  >
105 
119 template <typename T
120 #if GDAL_VERSION_NUM >= 2030000
121  ,
122  T (OGRFeature::*ptr_to_function)(int) const
123 #else
124  ,
125  T (OGRFeature::*ptr_to_function)(int)
126 #endif
127  ,
128  typename FinalReturnType = T>
130 {
131 public:
132  static FinalReturnType call(OGRFeature& f, int index)
133  {
134  return (f.*ptr_to_function)(index);
135  }
136 };
138 
151 template <typename FinalReturnType = std::vector<std::string>>
153 {
154 public:
155  static FinalReturnType call(OGRFeature& f, int index)
156  {
157  char** sl = f.GetFieldAsStringList(index);
158  FinalReturnType res(sl, sl + CSLCount(sl));
159  return res;
160  }
161 };
163 
176 template <typename T, void (OGRFeature::*ptr_to_function)(int, T value), typename ActualParamType = T>
178 {
179 public:
180  static void call(OGRFeature& f, int index, T const& value)
181  {
182  (f.*ptr_to_function)(index, value);
183  }
184 };
186 
200 template <typename T
201 #if GDAL_VERSION_NUM >= 2030000
202  ,
203  T const* (OGRFeature::*ptr_to_function)(int, int*)const
204 #else
205  ,
206  T const* (OGRFeature::*ptr_to_function)(int, int*)
207 #endif
208  ,
209  typename FinalReturnType = std::vector<T>>
211 {
212 public:
213  static FinalReturnType call(OGRFeature& f, int index)
214  {
215  int nb = 0;
216  T const* raw_container = (f.*ptr_to_function)(index, &nb);
217  const FinalReturnType res(raw_container + 0, raw_container + nb);
218  return res;
219  }
220 };
222 
223 /*===========================================================================*/
234 template <typename T
235 #if GDAL_VERSION_NUM >= 2030000
236  ,
237  void (OGRFeature::*ptr_to_function)(int, int, const T*)
238 #else
239  ,
240  void (OGRFeature::*ptr_to_function)(int, int, T*) // not const-correct
241 #endif
242  ,
243  typename ActualParamType = std::vector<T>, bool Is_contiguous = boost::is_contiguous<ActualParamType>::value>
245 
248 template <typename T
249 #if GDAL_VERSION_NUM >= 2030000
250  ,
251  void (OGRFeature::*ptr_to_function)(int, int, const T*)
252 #else
253  ,
254  void (OGRFeature::*ptr_to_function)(int, int, T*) // not const-correct
255 #endif
256  ,
257  typename ActualParamType>
259 {
260 public:
261  static void call(OGRFeature& f, int index, ActualParamType const& container)
262  {
263  const int nb = boost::size(container);
264  (f.*ptr_to_function)(index, nb, const_cast<T*>(&container[0]));
265  }
266 };
268 
271 template <typename T
272 #if GDAL_VERSION_NUM >= 2030000
273  ,
274  void (OGRFeature::*ptr_to_function)(int, int, const T*)
275 #else
276  ,
277  void (OGRFeature::*ptr_to_function)(int, int, T*) // not const-correct
278 #endif
279  ,
280  typename ActualParamType>
282 {
283 public:
284  static void call(OGRFeature& f, int index, ActualParamType const& container)
285  {
286  const int nb = boost::size(container);
287  std::vector<T> v(boost::begin(container), boost::end(container));
288  (f.*ptr_to_function)(index, nb, &v[0]);
289  }
290 };
292 
304 template <typename ActualParamType>
306 {
307 public:
308  static void call(OGRFeature& f, int index, ActualParamType const& container)
309  {
310  f.SetField(index, StringListConverter(container).to_ogr());
311  }
312 };
314 
328 template <typename T
329 #if GDAL_VERSION_NUM >= 2030000
330  ,
331  void (OGRFeature::*ptr_to_function)(int, int, const T*)
332 #else
333  ,
334  void (OGRFeature::*ptr_to_function)(int, int, T*) // not const-correct
335 #endif
336  ,
337  typename ActualParamType = std::vector<T>>
339 {
340 public:
341  static void call(OGRFeature& f, int index, ActualParamType const& container)
342  {
344  }
345 };
347 
354 typedef mpl::map<mpl::pair<mpl::int_<OFTInteger>, MemberGetterPtr<int, &OGRFeature::GetFieldAsInteger>>,
355  mpl::pair<mpl::int_<OFTIntegerList>, MemberContainerGetterPtr<int, &OGRFeature::GetFieldAsIntegerList>>,
356  mpl::pair<mpl::int_<OFTReal>, MemberGetterPtr<double, &OGRFeature::GetFieldAsDouble>>,
357  mpl::pair<mpl::int_<OFTRealList>, MemberContainerGetterPtr<double, &OGRFeature::GetFieldAsDoubleList>>,
358  mpl::pair<mpl::int_<OFTString>, MemberGetterPtr<char const*, &OGRFeature::GetFieldAsString, std::string>>,
359  mpl::pair<mpl::int_<OFTStringList>, StringListMemberGetterPtr<std::vector<std::string>>>,
360  mpl::pair<mpl::int_<OFTInteger64>, MemberGetterPtr<GIntBig, &OGRFeature::GetFieldAsInteger64>>,
361  mpl::pair<mpl::int_<OFTInteger64List>, MemberContainerGetterPtr<GIntBig, &OGRFeature::GetFieldAsInteger64List>>>
363 
370 typedef mpl::map<mpl::pair<mpl::int_<OFTInteger>, MemberSetterPtr<int, &OGRFeature::SetField>>,
371  mpl::pair<mpl::int_<OFTIntegerList>, MemberContainerSetterPtr<int, &OGRFeature::SetField>>,
372  mpl::pair<mpl::int_<OFTReal>, MemberSetterPtr<double, &OGRFeature::SetField>>,
373  mpl::pair<mpl::int_<OFTRealList>, MemberContainerSetterPtr<double, &OGRFeature::SetField>>,
374  mpl::pair<mpl::int_<OFTString>, MemberSetterPtr<char const*, &OGRFeature::SetField /*, std::string*/>>,
375  mpl::pair<mpl::int_<OFTStringList>, StringListMemberSetterPtr<std::vector<std::string>>>,
376  mpl::pair<mpl::int_<OFTInteger64>, MemberSetterPtr<GIntBig, &OGRFeature::SetField>>,
377  mpl::pair<mpl::int_<OFTInteger64List>, MemberContainerSetterPtr<const GIntBig, &OGRFeature::SetField>>>
379 
389 template <typename T>
391 {
392  typedef T type;
393  static T const& convert(T const& value)
394  {
395  return value;
396  }
397 };
399 
403 template <typename T, std::size_t N>
405 {
406  typedef T* type;
407  static T const* convert(const T value[N])
408  {
409  return &value[0];
410  }
411 };
412 
416 template <>
417 struct CppToOGRConverter_trait<std::string>
418 {
419  typedef char* type;
420  static char const* convert(std::string const& value)
421  {
422  return value.c_str();
423  }
424 };
426 
427 } // namespace internal
428 }
429 } // end namespace otb::ogr
430 
431 /*===========================================================================*/
432 /*=======================[ otb::ogr::Field functions ]=======================*/
433 /*===========================================================================*/
434 
436 {
437  assert(m_Feature && "OGR Fields must be associated to a valid feature");
438  assert(m_index < m_Feature->GetFieldCount() && "Out-of-range index for a OGR field");
439  assert(m_Feature->GetFieldDefnRef(m_index) && "No definition available for the OGR field");
440 }
441 
442 template <typename T>
443 inline void otb::ogr::Field::SetValue(T const& value)
444 {
445  CheckInvariants();
446  typedef internal::CppToOGRConverter_trait<T> Converter;
447  typedef typename Converter::type InterfaceType;
448  // uncomment the next line to debug the InterfaceType computed
449  // boost::mpl::print<typename internal::CppToOGRConverter_trait<T>::type> interface_type; (void) interface_type;
450  BOOST_MPL_ASSERT_MSG(!boost::is_array<InterfaceType>::value, InterFaceType_Cant_Be_An_array, (T, InterfaceType));
451  typedef typename boost::mpl::at<internal::FieldType_Map, InterfaceType>::type Kind;
452  BOOST_MPL_ASSERT_MSG(!(boost::is_same<Kind, boost::mpl::void_>::value), UNEXPECTED_KIND_TYPE, (T, InterfaceType, Kind));
453  // const int VALUE = Kind::value;
454  assert(m_Definition.GetType() == Kind::value && "OGR field type mismatches the type of new field value");
455  typedef typename boost::mpl::at<internal::FieldSetters_Map, Kind>::type SetterType;
456  // If you experience a static assertion failure in the line below, it means
457  // the type of the parameter is not supported to set a field.
458  BOOST_MPL_ASSERT_NOT((boost::is_same<SetterType, boost::mpl::void_>));
459  SetterType::call(*m_Feature, m_index, Converter::convert(value));
460 }
461 
462 template <typename T>
464 {
465  CheckInvariants();
466  assert(HasBeenSet() && "Cannot access the value of a field that hasn't been set");
467  typedef typename boost::mpl::at<internal::FieldType_Map, T>::type Kind;
468  // const int VALUE = Kind::value;
469  BOOST_STATIC_ASSERT(!(boost::is_same<Kind, boost::mpl::void_>::value));
470  typedef typename boost::mpl::at<internal::FieldGetters_Map, Kind>::type GetterType;
471  // If you experience a static assertion failure in the line below, it means
472  // the field cannot be extracted into the type requested.
473  BOOST_STATIC_ASSERT(!(boost::is_same<GetterType, boost::mpl::void_>::value));
474  return GetterType::call(*m_Feature, m_index);
475 }
476 
477 inline std::ostream& otb::ogr::Field::PrintSelf(std::ostream& os, itk::Indent indent) const
478 {
479  CheckInvariants();
480  return UncheckedPrintSelf(os, indent);
481 }
482 
483 inline bool otb::ogr::Field::HasBeenSet() const
484 {
485  CheckInvariants();
486  return UncheckedHasBeenSet();
487 }
488 
489 inline void otb::ogr::Field::Unset() const
490 {
491  CheckInvariants();
492  UncheckedUnset();
493 }
494 
495 inline void otb::ogr::Field::Assign(Field const& f)
496 {
497  CheckInvariants();
498  f.CheckInvariants();
499  assert(f.GetType() == this->GetType() && "Cannot assign from a field that doesn't have the same definition");
500  // We can't assume the following as sometimes field names are altered by the
501  // datasource driver; for instance, shp driver truncates field names to 8
502  // characters.
503  // assert(f.GetDefinition() == this->GetDefinition() && "Cannot assign from a field that doesn't have the same definition");
504  UncheckedAssign(f);
505  CheckInvariants();
506 }
507 
508 inline OGRField& otb::ogr::Field::ogr()
509 {
510  CheckInvariants();
511  OGRField* f = m_Feature->GetRawFieldRef(m_index);
512  assert(f && "The field obtained shall not be null");
513  return *f;
514 }
515 
516 inline OGRField& otb::ogr::Field::ogr() const
517 {
518  return const_cast<Field*>(this)->ogr();
519 }
520 
521 #endif // otbOGRFieldWrapper_hxx
otb::ogr::Field::CheckInvariants
void CheckInvariants() const
Definition: otbOGRFieldWrapper.hxx:435
otb::ogr::internal::FieldType_Map
mpl::map< mpl::pair< int, mpl::int_< OFTInteger > >, mpl::pair< std::vector< int >, mpl::int_< OFTIntegerList > >, mpl::pair< double, mpl::int_< OFTReal > >, mpl::pair< std::vector< double >, mpl::int_< OFTRealList > >, mpl::pair< std::string, mpl::int_< OFTString > >, mpl::pair< char *, mpl::int_< OFTString > >, mpl::pair< char const *, mpl::int_< OFTString > >, mpl::pair< std::vector< std::string >, mpl::int_< OFTStringList > >, mpl::pair< GIntBig, mpl::int_< OFTInteger64 > >, mpl::pair< std::vector< GIntBig >, mpl::int_< OFTInteger64List > > > FieldType_Map
Definition: otbOGRFieldWrapper.hxx:104
otb::ogr::internal::MemberContainerGetterPtr::call
static FinalReturnType call(OGRFeature &f, int index)
Definition: otbOGRFieldWrapper.hxx:213
otb::ogr::Field::SetValue
void SetValue(T const &value)
Definition: otbOGRFieldWrapper.hxx:443
otb::ogr::internal::FieldGetters_Map
mpl::map< mpl::pair< mpl::int_< OFTInteger >, MemberGetterPtr< int, &OGRFeature::GetFieldAsInteger > >, mpl::pair< mpl::int_< OFTIntegerList >, MemberContainerGetterPtr< int, &OGRFeature::GetFieldAsIntegerList > >, mpl::pair< mpl::int_< OFTReal >, MemberGetterPtr< double, &OGRFeature::GetFieldAsDouble > >, mpl::pair< mpl::int_< OFTRealList >, MemberContainerGetterPtr< double, &OGRFeature::GetFieldAsDoubleList > >, mpl::pair< mpl::int_< OFTString >, MemberGetterPtr< char const *, &OGRFeature::GetFieldAsString, std::string > >, mpl::pair< mpl::int_< OFTStringList >, StringListMemberGetterPtr< std::vector< std::string > > >, mpl::pair< mpl::int_< OFTInteger64 >, MemberGetterPtr< GIntBig, &OGRFeature::GetFieldAsInteger64 > >, mpl::pair< mpl::int_< OFTInteger64List >, MemberContainerGetterPtr< GIntBig, &OGRFeature::GetFieldAsInteger64List > > > FieldGetters_Map
Definition: otbOGRFieldWrapper.hxx:362
otbOGRFieldWrapper.h
otb::ogr::internal::MemberGetterPtr::call
static FinalReturnType call(OGRFeature &f, int index)
Definition: otbOGRFieldWrapper.hxx:132
otb::ogr::internal::TagDispatchMemberContainerSetterPtr< T, ptr_to_function, ActualParamType, false >
Definition: otbOGRFieldWrapper.hxx:281
otb::ogr::internal::CppToOGRConverter_trait< T[N]>::convert
static T const * convert(const T value[N])
Definition: otbOGRFieldWrapper.hxx:407
otb::ogr::StringListConverter
Helper class to convert a set of standard C++ string into char** as OGR API expects.
Definition: otbOGRHelpers.h:73
otb::ogr::internal::StringListMemberGetterPtr
Definition: otbOGRFieldWrapper.hxx:152
otb::ogr::Field::Unset
void Unset() const
Unsets the value of the field.
Definition: otbOGRFieldWrapper.hxx:489
otb::ogr::internal::MemberGetterPtr
Definition: otbOGRFieldWrapper.hxx:129
otb::ogr::internal::StringListMemberSetterPtr
Definition: otbOGRFieldWrapper.hxx:305
otb::ogr::Field::PrintSelf
std::ostream & PrintSelf(std::ostream &os, itk::Indent indent) const
Definition: otbOGRFieldWrapper.hxx:477
otb::ogr::internal::MemberSetterPtr
Definition: otbOGRFieldWrapper.hxx:177
otb::ogr::internal::StringListMemberGetterPtr::call
static FinalReturnType call(OGRFeature &f, int index)
Definition: otbOGRFieldWrapper.hxx:155
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::ogr::internal::MemberContainerSetterPtr::call
static void call(OGRFeature &f, int index, ActualParamType const &container)
Definition: otbOGRFieldWrapper.hxx:341
otb::ogr::internal::CppToOGRConverter_trait< T[N]>::type
T * type
Definition: otbOGRFieldWrapper.hxx:406
otb::ogr::internal::MemberSetterPtr::call
static void call(OGRFeature &f, int index, T const &value)
Definition: otbOGRFieldWrapper.hxx:180
otb::ogr::Field::HasBeenSet
bool HasBeenSet() const
Tells whether the field value has been set.
Definition: otbOGRFieldWrapper.hxx:483
otb::ogr::Field
Encapsulation of OGRField Instances of Field are expected to be built from an existing Feature with w...
Definition: otbOGRFieldWrapper.h:117
otb::ogr::internal::MemberContainerGetterPtr
Definition: otbOGRFieldWrapper.hxx:210
otb::ogr::internal::FieldSetters_Map
mpl::map< mpl::pair< mpl::int_< OFTInteger >, MemberSetterPtr< int, &OGRFeature::SetField > >, mpl::pair< mpl::int_< OFTIntegerList >, MemberContainerSetterPtr< int, &OGRFeature::SetField > >, mpl::pair< mpl::int_< OFTReal >, MemberSetterPtr< double, &OGRFeature::SetField > >, mpl::pair< mpl::int_< OFTRealList >, MemberContainerSetterPtr< double, &OGRFeature::SetField > >, mpl::pair< mpl::int_< OFTString >, MemberSetterPtr< char const *, &OGRFeature::SetField > >, mpl::pair< mpl::int_< OFTStringList >, StringListMemberSetterPtr< std::vector< std::string > > >, mpl::pair< mpl::int_< OFTInteger64 >, MemberSetterPtr< GIntBig, &OGRFeature::SetField > >, mpl::pair< mpl::int_< OFTInteger64List >, MemberContainerSetterPtr< const GIntBig, &OGRFeature::SetField > > > FieldSetters_Map
Definition: otbOGRFieldWrapper.hxx:378
otb::ogr::internal::CppToOGRConverter_trait< std::string >::type
char * type
Definition: otbOGRFieldWrapper.hxx:419
otb::ogr::internal::MemberContainerSetterPtr
Definition: otbOGRFieldWrapper.hxx:338
otb::ogr::internal::TagDispatchMemberContainerSetterPtr< T, ptr_to_function, ActualParamType, false >::call
static void call(OGRFeature &f, int index, ActualParamType const &container)
Definition: otbOGRFieldWrapper.hxx:284
otb::ogr::internal::CppToOGRConverter_trait
Trait class for converting C++ types into OGR field setter compatible types.
Definition: otbOGRFieldWrapper.hxx:390
otb::ogr::Field::GetValue
T GetValue() const
Definition: otbOGRFieldWrapper.hxx:463
otb::ogr::Field::ogr
OGRField & ogr()
Definition: otbOGRFieldWrapper.hxx:508
otb::ogr::internal::TagDispatchMemberContainerSetterPtr< T, ptr_to_function, ActualParamType, true >::call
static void call(OGRFeature &f, int index, ActualParamType const &container)
Definition: otbOGRFieldWrapper.hxx:261
otb::ogr::internal::CppToOGRConverter_trait< std::string >::convert
static char const * convert(std::string const &value)
Definition: otbOGRFieldWrapper.hxx:420
otbOGRHelpers.h
otb::ogr::internal::StringListMemberSetterPtr::call
static void call(OGRFeature &f, int index, ActualParamType const &container)
Definition: otbOGRFieldWrapper.hxx:308
otb::ogr::internal::CppToOGRConverter_trait::convert
static T const & convert(T const &value)
Definition: otbOGRFieldWrapper.hxx:393
otb::ogr::internal::TagDispatchMemberContainerSetterPtr< T, ptr_to_function, ActualParamType, true >
Definition: otbOGRFieldWrapper.hxx:258
otb::ogr::Field::Assign
void Assign(Field const &f)
Definition: otbOGRFieldWrapper.hxx:495
otb::ogr::Field::GetType
OGRFieldType GetType() const
Field type accessor.
Definition: otbOGRFieldWrapper.h:134
otb::ogr::Field::m_index
int m_index
Definition: otbOGRFieldWrapper.h:240
otb::ogr::internal::CppToOGRConverter_trait::type
T type
Definition: otbOGRFieldWrapper.hxx:392
otb::ogr::Field::m_Feature
std::shared_ptr< OGRFeature > & m_Feature
Link to the actual OGRFeature in charge of the fields.
Definition: otbOGRFieldWrapper.h:233
otb::ogr::internal::TagDispatchMemberContainerSetterPtr
Dispatcher function for the Field Setter. The container-field setters from OGR API have a C API....
Definition: otbOGRFieldWrapper.hxx:244