LCOV - code coverage report
Current view: top level - ogr - ogrfeaturedefn.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 327 356 91.9 %
Date: 2024-11-21 22:18:42 Functions: 56 61 91.8 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  The OGRFeatureDefn class implementation.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
       9             :  * Copyright (c) 2009-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "ogr_feature.h"
      16             : 
      17             : #include <algorithm>
      18             : #include <cassert>
      19             : #include <cstring>
      20             : 
      21             : #include "cpl_conv.h"
      22             : #include "cpl_error.h"
      23             : #include "cpl_string.h"
      24             : #include "ogr_api.h"
      25             : #include "ogr_core.h"
      26             : #include "ogr_p.h"
      27             : #include "ograpispy.h"
      28             : 
      29             : /************************************************************************/
      30             : /*                           OGRFeatureDefn()                           */
      31             : /************************************************************************/
      32             : 
      33             : /**
      34             :  * \brief Constructor.
      35             :  *
      36             :  * The OGRFeatureDefn maintains a reference count, but this starts at
      37             :  * zero.  It is mainly intended to represent a count of OGRFeature's
      38             :  * based on this definition.
      39             :  *
      40             :  * This method is the same as the C function OGR_FD_Create().
      41             :  *
      42             :  * @param pszName the name to be assigned to this layer/class.  It does not
      43             :  * need to be unique.
      44             :  */
      45             : 
      46       67794 : OGRFeatureDefn::OGRFeatureDefn(const char *pszName)
      47             : {
      48       67794 :     pszFeatureClassName = CPLStrdup(pszName);
      49             :     apoGeomFieldDefn.emplace_back(
      50       67794 :         std::make_unique<OGRGeomFieldDefn>("", wkbUnknown));
      51       67794 : }
      52             : 
      53             : /************************************************************************/
      54             : /*                           OGR_FD_Create()                            */
      55             : /************************************************************************/
      56             : /**
      57             :  * \brief Create a new feature definition object to hold the field definitions.
      58             :  *
      59             :  * The OGRFeatureDefn maintains a reference count, but this starts at
      60             :  * zero, and should normally be incremented by the owner.
      61             :  *
      62             :  * This function is the same as the C++ method
      63             :  * OGRFeatureDefn::OGRFeatureDefn().
      64             :  *
      65             :  * @param pszName the name to be assigned to this layer/class.  It does not
      66             :  * need to be unique.
      67             :  * @return handle to the newly created feature definition.
      68             :  */
      69             : 
      70         118 : OGRFeatureDefnH OGR_FD_Create(const char *pszName)
      71             : 
      72             : {
      73         118 :     return OGRFeatureDefn::ToHandle(new OGRFeatureDefn(pszName));
      74             : }
      75             : 
      76             : /************************************************************************/
      77             : /*                          ~OGRFeatureDefn()                           */
      78             : /************************************************************************/
      79             : 
      80      119642 : OGRFeatureDefn::~OGRFeatureDefn()
      81             : 
      82             : {
      83       67781 :     if (nRefCount != 0)
      84             :     {
      85          80 :         CPLDebug("OGRFeatureDefn",
      86             :                  "OGRFeatureDefn %s with a ref count of %d deleted!",
      87          80 :                  pszFeatureClassName, nRefCount);
      88             :     }
      89             : 
      90       67781 :     CPLFree(pszFeatureClassName);
      91      119642 : }
      92             : 
      93             : /************************************************************************/
      94             : /*                           OGR_FD_Destroy()                           */
      95             : /************************************************************************/
      96             : /**
      97             :  * \brief Destroy a feature definition object and release all memory associated
      98             :  * with it.
      99             :  *
     100             :  * This function is the same as the C++ method
     101             :  * OGRFeatureDefn::~OGRFeatureDefn().
     102             :  *
     103             :  * @param hDefn handle to the feature definition to be destroyed.
     104             :  */
     105             : 
     106           0 : void OGR_FD_Destroy(OGRFeatureDefnH hDefn)
     107             : 
     108             : {
     109           0 :     delete OGRFeatureDefn::FromHandle(hDefn);
     110           0 : }
     111             : 
     112             : /************************************************************************/
     113             : /*                              Release()                               */
     114             : /************************************************************************/
     115             : 
     116             : /**
     117             :  * \fn void OGRFeatureDefn::Release();
     118             :  *
     119             :  * \brief Drop a reference to this object, and destroy if no longer referenced.
     120             :  */
     121             : 
     122     2435740 : void OGRFeatureDefn::Release()
     123             : 
     124             : {
     125     2435740 :     if (Dereference() <= 0)
     126       67312 :         delete this;
     127     2435740 : }
     128             : 
     129             : /************************************************************************/
     130             : /*                           OGR_FD_Release()                           */
     131             : /************************************************************************/
     132             : 
     133             : /**
     134             :  * \brief Drop a reference, and destroy if unreferenced.
     135             :  *
     136             :  * This function is the same as the C++ method OGRFeatureDefn::Release().
     137             :  *
     138             :  * @param hDefn handle to the feature definition to be released.
     139             :  */
     140             : 
     141      125470 : void OGR_FD_Release(OGRFeatureDefnH hDefn)
     142             : 
     143             : {
     144      125470 :     OGRFeatureDefn::FromHandle(hDefn)->Release();
     145      125470 : }
     146             : 
     147             : /************************************************************************/
     148             : /*                               Clone()                                */
     149             : /************************************************************************/
     150             : 
     151             : /**
     152             :  * \fn OGRFeatureDefn *OGRFeatureDefn::Clone() const;
     153             :  *
     154             :  * \brief Create a copy of this feature definition.
     155             :  *
     156             :  * Creates a deep copy of the feature definition.
     157             :  * The reference counter of the copy is initialized at 0.
     158             :  *
     159             :  * @return the copy.
     160             :  */
     161             : 
     162         626 : OGRFeatureDefn *OGRFeatureDefn::Clone() const
     163             : 
     164             : {
     165         626 :     OGRFeatureDefn *poCopy = new OGRFeatureDefn(GetName());
     166             : 
     167             :     {
     168         626 :         const int nFieldCount = GetFieldCount();
     169         626 :         poCopy->apoFieldDefn.reserve(nFieldCount);
     170        3566 :         for (int i = 0; i < nFieldCount; i++)
     171        2940 :             poCopy->AddFieldDefn(GetFieldDefn(i));
     172             :     }
     173             : 
     174             :     {
     175             :         // Remove the default geometry field created instantiation.
     176         626 :         poCopy->DeleteGeomFieldDefn(0);
     177         626 :         const int nGeomFieldCount = GetGeomFieldCount();
     178         626 :         poCopy->apoGeomFieldDefn.reserve(nGeomFieldCount);
     179         978 :         for (int i = 0; i < nGeomFieldCount; i++)
     180         352 :             poCopy->AddGeomFieldDefn(GetGeomFieldDefn(i));
     181             :     }
     182             : 
     183         626 :     return poCopy;
     184             : }
     185             : 
     186             : /************************************************************************/
     187             : /*                              SetName()                               */
     188             : /************************************************************************/
     189             : 
     190             : /**
     191             :  * \brief Change name of this OGRFeatureDefn.
     192             :  *
     193             :  * To rename a layer, do not use this function directly, but use
     194             :  * OGRLayer::Rename() instead.
     195             :  *
     196             :  * @param pszName feature definition name
     197             :  * @since GDAL 2.3
     198             :  */
     199         256 : void OGRFeatureDefn::SetName(const char *pszName)
     200             : {
     201         256 :     if (m_bSealed)
     202             :     {
     203           1 :         CPLError(CE_Failure, CPLE_AppDefined,
     204             :                  "OGRFeatureDefn::SetName() not allowed on a sealed object");
     205           1 :         return;
     206             :     }
     207         255 :     CPLFree(pszFeatureClassName);
     208         255 :     pszFeatureClassName = CPLStrdup(pszName);
     209             : }
     210             : 
     211             : /************************************************************************/
     212             : /*                              GetName()                               */
     213             : /************************************************************************/
     214             : 
     215             : /**
     216             :  * \fn const char *OGRFeatureDefn::GetName();
     217             :  *
     218             :  * \brief Get name of this OGRFeatureDefn.
     219             :  *
     220             :  * This method is the same as the C function OGR_FD_GetName().
     221             :  *
     222             :  * @return the name.  This name is internal and should not be modified, or
     223             :  * freed.
     224             :  */
     225     1247960 : const char *OGRFeatureDefn::GetName() const
     226             : {
     227     1247960 :     return pszFeatureClassName;
     228             : }
     229             : 
     230             : /************************************************************************/
     231             : /*                           OGR_FD_GetName()                           */
     232             : /************************************************************************/
     233             : /**
     234             :  * \brief Get name of the OGRFeatureDefn passed as an argument.
     235             :  *
     236             :  * This function is the same as the C++ method OGRFeatureDefn::GetName().
     237             :  *
     238             :  * @param hDefn handle to the feature definition to get the name from.
     239             :  * @return the name.  This name is internal and should not be modified, or
     240             :  * freed.
     241             :  */
     242             : 
     243         107 : const char *OGR_FD_GetName(OGRFeatureDefnH hDefn)
     244             : 
     245             : {
     246         107 :     return OGRFeatureDefn::FromHandle(hDefn)->GetName();
     247             : }
     248             : 
     249             : /************************************************************************/
     250             : /*                           GetFieldCount()                            */
     251             : /************************************************************************/
     252             : 
     253             : /**
     254             :  * \fn int OGRFeatureDefn::GetFieldCount() const;
     255             :  *
     256             :  * \brief Fetch number of fields on this feature.
     257             :  *
     258             :  * This method is the same as the C function OGR_FD_GetFieldCount().
     259             :  * @return count of fields.
     260             :  */
     261             : 
     262    46793700 : int OGRFeatureDefn::GetFieldCount() const
     263             : {
     264    46793700 :     return static_cast<int>(apoFieldDefn.size());
     265             : }
     266             : 
     267             : /************************************************************************/
     268             : /*                        OGR_FD_GetFieldCount()                        */
     269             : /************************************************************************/
     270             : 
     271             : /**
     272             :  * \brief Fetch number of fields on the passed feature definition.
     273             :  *
     274             :  * This function is the same as the C++ OGRFeatureDefn::GetFieldCount().
     275             :  *
     276             :  * @param hDefn handle to the feature definition to get the fields count from.
     277             :  * @return count of fields.
     278             :  */
     279             : 
     280       48418 : int OGR_FD_GetFieldCount(OGRFeatureDefnH hDefn)
     281             : 
     282             : {
     283             : #ifdef OGRAPISPY_ENABLED
     284       48418 :     if (bOGRAPISpyEnabled)
     285           6 :         OGRAPISpy_FD_GetFieldCount(hDefn);
     286             : #endif
     287             : 
     288       48418 :     return OGRFeatureDefn::FromHandle(hDefn)->GetFieldCount();
     289             : }
     290             : 
     291             : /************************************************************************/
     292             : /*                            GetFieldDefn()                            */
     293             : /************************************************************************/
     294             : 
     295             : /**
     296             :  * \brief Fetch field definition.
     297             :  *
     298             :  * This method is the same as the C function OGR_FD_GetFieldDefn().
     299             :  *
     300             :  * @param iField the field to fetch, between 0 and GetFieldCount() - 1.
     301             :  *
     302             :  * @return a pointer to an internal field definition object or NULL if invalid
     303             :  * index.  This object should not be modified or freed by the application.
     304             :  */
     305             : 
     306    20744900 : OGRFieldDefn *OGRFeatureDefn::GetFieldDefn(int iField)
     307             : 
     308             : {
     309    20744900 :     if (iField < 0 || iField >= GetFieldCount())
     310             :     {
     311          11 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iField);
     312          11 :         return nullptr;
     313             :     }
     314             : 
     315    20744900 :     return apoFieldDefn[iField].get();
     316             : }
     317             : 
     318             : /**
     319             :  * \brief Fetch field definition.
     320             :  *
     321             :  * This method is the same as the C function OGR_FD_GetFieldDefn().
     322             :  *
     323             :  * @param iField the field to fetch, between 0 and GetFieldCount() - 1.
     324             :  *
     325             :  * @return a pointer to an internal field definition object or NULL if invalid
     326             :  * index.  This object should not be modified or freed by the application.
     327             :  *
     328             :  * @since GDAL 2.3
     329             :  */
     330             : 
     331    17970900 : const OGRFieldDefn *OGRFeatureDefn::GetFieldDefn(int iField) const
     332             : 
     333             : {
     334    17970900 :     if (iField < 0 || iField >= GetFieldCount())
     335             :     {
     336           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iField);
     337           0 :         return nullptr;
     338             :     }
     339             : 
     340    17970900 :     return apoFieldDefn[iField].get();
     341             : }
     342             : 
     343             : /************************************************************************/
     344             : /*                        OGR_FD_GetFieldDefn()                         */
     345             : /************************************************************************/
     346             : 
     347             : /**
     348             :  * \brief Fetch field definition of the passed feature definition.
     349             :  *
     350             :  * This function is the same as the C++ method
     351             :  * OGRFeatureDefn::GetFieldDefn().
     352             :  *
     353             :  * @param hDefn handle to the feature definition to get the field definition
     354             :  * from.
     355             :  * @param iField the field to fetch, between 0 and GetFieldCount()-1.
     356             :  *
     357             :  * @return a handle to an internal field definition object or NULL if invalid
     358             :  * index.  This object should not be modified or freed by the application.
     359             :  */
     360             : 
     361      221592 : OGRFieldDefnH OGR_FD_GetFieldDefn(OGRFeatureDefnH hDefn, int iField)
     362             : 
     363             : {
     364      221592 :     OGRFieldDefnH hFieldDefnH = OGRFieldDefn::ToHandle(
     365      221592 :         OGRFeatureDefn::FromHandle(hDefn)->GetFieldDefn(iField));
     366             : 
     367             : #ifdef OGRAPISPY_ENABLED
     368      221592 :     if (bOGRAPISpyEnabled)
     369           2 :         OGRAPISpy_FD_GetFieldDefn(hDefn, iField, hFieldDefnH);
     370             : #endif
     371             : 
     372      221592 :     return hFieldDefnH;
     373             : }
     374             : 
     375             : //! @cond Doxygen_Suppress
     376             : 
     377             : /************************************************************************/
     378             : /*                        ReserveSpaceForFields()                       */
     379             : /************************************************************************/
     380             : 
     381         938 : void OGRFeatureDefn::ReserveSpaceForFields(int nFieldCountIn)
     382             : {
     383         938 :     apoFieldDefn.reserve(nFieldCountIn);
     384         938 : }
     385             : 
     386             : //! @endcond
     387             : 
     388             : /************************************************************************/
     389             : /*                            AddFieldDefn()                            */
     390             : /************************************************************************/
     391             : 
     392             : /**
     393             :  * \brief Add a new field definition.
     394             :  *
     395             :  * To add a new field definition to a layer definition, do not use this
     396             :  * function directly, but use OGRLayer::CreateField() instead.
     397             :  *
     398             :  * This method should only be called while there are no OGRFeature
     399             :  * objects in existence based on this OGRFeatureDefn.  The OGRFieldDefn
     400             :  * passed in is copied, and remains the responsibility of the caller.
     401             :  *
     402             :  * This method is the same as the C function OGR_FD_AddFieldDefn().
     403             :  *
     404             :  * @param poNewDefn the definition of the new field.
     405             :  */
     406             : 
     407      704070 : void OGRFeatureDefn::AddFieldDefn(const OGRFieldDefn *poNewDefn)
     408             : 
     409             : {
     410      704070 :     if (m_bSealed)
     411             :     {
     412           2 :         CPLError(
     413             :             CE_Failure, CPLE_AppDefined,
     414             :             "OGRFeatureDefn::AddFieldDefn() not allowed on a sealed object");
     415           2 :         return;
     416             :     }
     417      704068 :     apoFieldDefn.emplace_back(std::make_unique<OGRFieldDefn>(poNewDefn));
     418             : }
     419             : 
     420             : /************************************************************************/
     421             : /*                        OGR_FD_AddFieldDefn()                         */
     422             : /************************************************************************/
     423             : 
     424             : /**
     425             :  * \brief Add a new field definition to the passed feature definition.
     426             :  *
     427             :  * To add a new field definition to a layer definition, do not use this
     428             :  * function directly, but use OGR_L_CreateField() instead.
     429             :  *
     430             :  * This function should only be called while there are no OGRFeature
     431             :  * objects in existence based on this OGRFeatureDefn.  The OGRFieldDefn
     432             :  * passed in is copied, and remains the responsibility of the caller.
     433             :  *
     434             :  * This function is the same as the C++ method OGRFeatureDefn::AddFieldDefn().
     435             :  *
     436             :  * @param hDefn handle to the feature definition to add the field definition
     437             :  * to.
     438             :  * @param hNewField handle to the new field definition.
     439             :  */
     440             : 
     441         413 : void OGR_FD_AddFieldDefn(OGRFeatureDefnH hDefn, OGRFieldDefnH hNewField)
     442             : 
     443             : {
     444         826 :     OGRFeatureDefn::FromHandle(hDefn)->AddFieldDefn(
     445         413 :         OGRFieldDefn::FromHandle(hNewField));
     446         413 : }
     447             : 
     448             : /************************************************************************/
     449             : /*                           DeleteFieldDefn()                          */
     450             : /************************************************************************/
     451             : 
     452             : /**
     453             :  * \brief Delete an existing field definition.
     454             :  *
     455             :  * To delete an existing field definition from a layer definition, do not use
     456             :  * this function directly, but use OGRLayer::DeleteField() instead.
     457             :  *
     458             :  * This method should only be called while there are no OGRFeature
     459             :  * objects in existence based on this OGRFeatureDefn.
     460             :  *
     461             :  * This method is the same as the C function OGR_FD_DeleteFieldDefn().
     462             :  *
     463             :  * @param iField the index of the field definition.
     464             :  * @return OGRERR_NONE in case of success.
     465             :  * @since OGR 1.9.0
     466             :  */
     467             : 
     468          75 : OGRErr OGRFeatureDefn::DeleteFieldDefn(int iField)
     469             : 
     470             : {
     471          75 :     if (m_bSealed)
     472             :     {
     473           1 :         CPLError(
     474             :             CE_Failure, CPLE_AppDefined,
     475             :             "OGRFeatureDefn::DeleteFieldDefn() not allowed on a sealed object");
     476           1 :         return OGRERR_FAILURE;
     477             :     }
     478          74 :     if (iField < 0 || iField >= GetFieldCount())
     479           0 :         return OGRERR_FAILURE;
     480             : 
     481          74 :     apoFieldDefn.erase(apoFieldDefn.begin() + iField);
     482          74 :     return OGRERR_NONE;
     483             : }
     484             : 
     485             : /************************************************************************/
     486             : /*                       OGR_FD_DeleteFieldDefn()                       */
     487             : /************************************************************************/
     488             : 
     489             : /**
     490             :  * \brief Delete an existing field definition.
     491             :  *
     492             :  * To delete an existing field definition from a layer definition, do not use
     493             :  * this function directly, but use OGR_L_DeleteField() instead.
     494             :  *
     495             :  * This method should only be called while there are no OGRFeature
     496             :  * objects in existence based on this OGRFeatureDefn.
     497             :  *
     498             :  * This method is the same as the C++ method OGRFeatureDefn::DeleteFieldDefn().
     499             :  *
     500             :  * @param hDefn handle to the feature definition.
     501             :  * @param iField the index of the field definition.
     502             :  * @return OGRERR_NONE in case of success.
     503             :  * @since OGR 1.9.0
     504             :  */
     505             : 
     506           0 : OGRErr OGR_FD_DeleteFieldDefn(OGRFeatureDefnH hDefn, int iField)
     507             : 
     508             : {
     509           0 :     return OGRFeatureDefn::FromHandle(hDefn)->DeleteFieldDefn(iField);
     510             : }
     511             : 
     512             : /************************************************************************/
     513             : /*                         ReorderFieldDefns()                          */
     514             : /************************************************************************/
     515             : 
     516             : /**
     517             :  * \brief Reorder the field definitions in the array of the feature definition
     518             :  *
     519             :  * To reorder the field definitions in a layer definition, do not use this
     520             :  * function directly, but use OGR_L_ReorderFields() instead.
     521             :  *
     522             :  * This method should only be called while there are no OGRFeature
     523             :  * objects in existence based on this OGRFeatureDefn.
     524             :  *
     525             :  * This method is the same as the C function OGR_FD_ReorderFieldDefns().
     526             :  *
     527             :  * @param panMap an array of GetFieldCount() elements which
     528             :  * is a permutation of [0, GetFieldCount()-1]. panMap is such that,
     529             :  * for each field definition at position i after reordering,
     530             :  * its position before reordering was panMap[i].
     531             :  * @return OGRERR_NONE in case of success.
     532             :  * @since OGR 1.9.0
     533             :  */
     534             : 
     535          74 : OGRErr OGRFeatureDefn::ReorderFieldDefns(const int *panMap)
     536             : 
     537             : {
     538          74 :     if (m_bSealed)
     539             :     {
     540           1 :         CPLError(CE_Failure, CPLE_AppDefined,
     541             :                  "OGRFeatureDefn::ReorderFieldDefns() not allowed on a sealed "
     542             :                  "object");
     543           1 :         return OGRERR_FAILURE;
     544             :     }
     545          73 :     const int nFieldCount = GetFieldCount();
     546          73 :     if (nFieldCount == 0)
     547           0 :         return OGRERR_NONE;
     548             : 
     549          73 :     const OGRErr eErr = OGRCheckPermutation(panMap, nFieldCount);
     550          73 :     if (eErr != OGRERR_NONE)
     551           0 :         return eErr;
     552             : 
     553          73 :     std::vector<std::unique_ptr<OGRFieldDefn>> apoFieldDefnNew(nFieldCount);
     554         511 :     for (int i = 0; i < nFieldCount; i++)
     555             :     {
     556         438 :         apoFieldDefnNew[i] = std::move(apoFieldDefn[panMap[i]]);
     557             :     }
     558          73 :     apoFieldDefn = std::move(apoFieldDefnNew);
     559          73 :     return OGRERR_NONE;
     560             : }
     561             : 
     562             : /************************************************************************/
     563             : /*                     OGR_FD_ReorderFieldDefns()                       */
     564             : /************************************************************************/
     565             : 
     566             : /**
     567             :  * \brief Reorder the field definitions in the array of the feature definition
     568             :  *
     569             :  * To reorder the field definitions in a layer definition, do not use this
     570             :  * function directly, but use OGR_L_ReorderFields() instead.
     571             :  *
     572             :  * This method should only be called while there are no OGRFeature
     573             :  * objects in existence based on this OGRFeatureDefn.
     574             :  *
     575             :  * This method is the same as the C++ method
     576             :  * OGRFeatureDefn::ReorderFieldDefns().
     577             :  *
     578             :  * @param hDefn handle to the feature definition.
     579             :  * @param panMap an array of GetFieldCount() elements which
     580             :  * is a permutation of [0, GetFieldCount()-1]. panMap is such that,
     581             :  * for each field definition at position i after reordering,
     582             :  * its position before reordering was panMap[i].
     583             :  * @return OGRERR_NONE in case of success.
     584             :  * @since OGR 2.1.0
     585             :  */
     586             : 
     587           0 : OGRErr OGR_FD_ReorderFieldDefns(OGRFeatureDefnH hDefn, const int *panMap)
     588             : 
     589             : {
     590           0 :     return OGRFeatureDefn::FromHandle(hDefn)->ReorderFieldDefns(panMap);
     591             : }
     592             : 
     593             : /************************************************************************/
     594             : /*                         GetGeomFieldCount()                          */
     595             : /************************************************************************/
     596             : 
     597             : /**
     598             :  * \fn int OGRFeatureDefn::GetGeomFieldCount() const;
     599             :  *
     600             :  * \brief Fetch number of geometry fields on this feature.
     601             :  *
     602             :  * This method is the same as the C function OGR_FD_GetGeomFieldCount().
     603             :  * @return count of geometry fields.
     604             :  *
     605             :  * @since GDAL 1.11
     606             :  */
     607    18417100 : int OGRFeatureDefn::GetGeomFieldCount() const
     608             : {
     609    18417100 :     return static_cast<int>(apoGeomFieldDefn.size());
     610             : }
     611             : 
     612             : /************************************************************************/
     613             : /*                      OGR_FD_GetGeomFieldCount()                      */
     614             : /************************************************************************/
     615             : 
     616             : /**
     617             :  * \brief Fetch number of geometry fields on the passed feature definition.
     618             :  *
     619             :  * This function is the same as the C++ OGRFeatureDefn::GetGeomFieldCount().
     620             :  *
     621             :  * @param hDefn handle to the feature definition to get the fields count from.
     622             :  * @return count of geometry fields.
     623             :  *
     624             :  * @since GDAL 1.11
     625             :  */
     626             : 
     627         293 : int OGR_FD_GetGeomFieldCount(OGRFeatureDefnH hDefn)
     628             : 
     629             : {
     630             : #ifdef OGRAPISPY_ENABLED
     631         293 :     if (bOGRAPISpyEnabled)
     632           2 :         OGRAPISpy_FD_GetGeomFieldCount(hDefn);
     633             : #endif
     634             : 
     635         293 :     return OGRFeatureDefn::FromHandle(hDefn)->GetGeomFieldCount();
     636             : }
     637             : 
     638             : /************************************************************************/
     639             : /*                           GetGeomFieldDefn()                         */
     640             : /************************************************************************/
     641             : 
     642             : /**
     643             :  * \brief Fetch geometry field definition.
     644             :  *
     645             :  * This method is the same as the C function OGR_FD_GetGeomFieldDefn().
     646             :  *
     647             :  * @param iGeomField the geometry field to fetch, between 0 and
     648             :  * GetGeomFieldCount() - 1.
     649             :  *
     650             :  * @return a pointer to an internal field definition object or NULL if invalid
     651             :  * index.  This object should not be modified or freed by the application.
     652             :  *
     653             :  * @since GDAL 1.11
     654             :  */
     655             : 
     656      915717 : OGRGeomFieldDefn *OGRFeatureDefn::GetGeomFieldDefn(int iGeomField)
     657             : 
     658             : {
     659      915717 :     if (iGeomField < 0 || iGeomField >= GetGeomFieldCount())
     660             :     {
     661           2 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iGeomField);
     662           2 :         return nullptr;
     663             :     }
     664             : 
     665      915715 :     return apoGeomFieldDefn[iGeomField].get();
     666             : }
     667             : 
     668             : /**
     669             :  * \brief Fetch geometry field definition.
     670             :  *
     671             :  * This method is the same as the C function OGR_FD_GetGeomFieldDefn().
     672             :  *
     673             :  * @param iGeomField the geometry field to fetch, between 0 and
     674             :  * GetGeomFieldCount() - 1.
     675             :  *
     676             :  * @return a pointer to an internal field definition object or NULL if invalid
     677             :  * index.  This object should not be modified or freed by the application.
     678             :  *
     679             :  * @since GDAL 2.3
     680             :  */
     681             : 
     682      675992 : const OGRGeomFieldDefn *OGRFeatureDefn::GetGeomFieldDefn(int iGeomField) const
     683             : 
     684             : {
     685      675992 :     if (iGeomField < 0 || iGeomField >= GetGeomFieldCount())
     686             :     {
     687           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iGeomField);
     688           0 :         return nullptr;
     689             :     }
     690             : 
     691      675992 :     return apoGeomFieldDefn[iGeomField].get();
     692             : }
     693             : 
     694             : /************************************************************************/
     695             : /*                      OGR_FD_GetGeomFieldDefn()                       */
     696             : /************************************************************************/
     697             : 
     698             : /**
     699             :  * \brief Fetch geometry field definition of the passed feature definition.
     700             :  *
     701             :  * This function is the same as the C++ method
     702             :  * OGRFeatureDefn::GetGeomFieldDefn().
     703             :  *
     704             :  * @param hDefn handle to the feature definition to get the field definition
     705             :  * from.
     706             :  * @param iGeomField the geometry field to fetch, between 0 and
     707             :  * GetGeomFieldCount() - 1.
     708             :  *
     709             :  * @return a handle to an internal field definition object or NULL if invalid
     710             :  * index.  This object should not be modified or freed by the application.
     711             :  *
     712             :  * @since GDAL 1.11
     713             :  */
     714             : 
     715         578 : OGRGeomFieldDefnH OGR_FD_GetGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField)
     716             : 
     717             : {
     718         578 :     OGRGeomFieldDefnH hGeomField = OGRGeomFieldDefn::ToHandle(
     719         578 :         OGRFeatureDefn::FromHandle(hDefn)->GetGeomFieldDefn(iGeomField));
     720             : 
     721             : #ifdef OGRAPISPY_ENABLED
     722         578 :     if (bOGRAPISpyEnabled)
     723           2 :         OGRAPISpy_FD_GetGeomFieldDefn(hDefn, iGeomField, hGeomField);
     724             : #endif
     725             : 
     726         578 :     return hGeomField;
     727             : }
     728             : 
     729             : /************************************************************************/
     730             : /*                          AddGeomFieldDefn()                          */
     731             : /************************************************************************/
     732             : 
     733             : /**
     734             :  * \brief Add a new geometry field definition.
     735             :  *
     736             :  * To add a new geometry field definition to a layer definition, do not use this
     737             :  * function directly, but use OGRLayer::CreateGeomField() instead.
     738             :  *
     739             :  * This method does an internal copy of the passed geometry field definition,
     740             :  * unless bCopy is set to FALSE (in which case it takes ownership of the
     741             :  * field definition.
     742             :  *
     743             :  * This method should only be called while there are no OGRFeature
     744             :  * objects in existence based on this OGRFeatureDefn.  The OGRGeomFieldDefn
     745             :  * passed in is copied, and remains the responsibility of the caller.
     746             :  *
     747             :  * This method is the same as the C function OGR_FD_AddGeomFieldDefn().
     748             :  *
     749             :  * @param poNewDefn the definition of the new geometry field.
     750             :  *
     751             :  * @since GDAL 1.11
     752             :  */
     753             : 
     754        7010 : void OGRFeatureDefn::AddGeomFieldDefn(const OGRGeomFieldDefn *poNewDefn)
     755             : {
     756        7010 :     if (m_bSealed)
     757             :     {
     758           1 :         CPLError(CE_Failure, CPLE_AppDefined,
     759             :                  "OGRFeatureDefn::AddGeomFieldDefn() not allowed on a sealed "
     760             :                  "object");
     761           1 :         return;
     762             :     }
     763             :     apoGeomFieldDefn.emplace_back(
     764        7009 :         std::make_unique<OGRGeomFieldDefn>(poNewDefn));
     765             : }
     766             : 
     767             : /**
     768             :  * \brief Add a new geometry field definition.
     769             :  *
     770             :  * To add a new geometry field definition to a layer definition, do not use this
     771             :  * function directly, but use OGRLayer::CreateGeomField() instead.
     772             :  *
     773             :  * This method takes ownership of the passed geometry field definition.
     774             :  *
     775             :  * This method should only be called while there are no OGRFeature
     776             :  * objects in existence based on this OGRFeatureDefn.
     777             :  *
     778             :  * @param poNewDefn the definition of the new geometry field.
     779             :  *
     780             :  * @since GDAL 3.4
     781             :  */
     782             : 
     783       11338 : void OGRFeatureDefn::AddGeomFieldDefn(
     784             :     std::unique_ptr<OGRGeomFieldDefn> &&poNewDefn)
     785             : {
     786       11338 :     apoGeomFieldDefn.emplace_back(std::move(poNewDefn));
     787       11338 : }
     788             : 
     789             : /************************************************************************/
     790             : /*                      OGR_FD_AddGeomFieldDefn()                       */
     791             : /************************************************************************/
     792             : 
     793             : /**
     794             :  * \brief Add a new field definition to the passed feature definition.
     795             :  *
     796             :  * To add a new field definition to a layer definition, do not use this
     797             :  * function directly, but use OGR_L_CreateGeomField() instead.
     798             :  *
     799             :  * This function should only be called while there are no OGRFeature
     800             :  * objects in existence based on this OGRFeatureDefn.  The OGRGeomFieldDefn
     801             :  * passed in is copied, and remains the responsibility of the caller.
     802             :  *
     803             :  * This function is the same as the C++ method
     804             :  * OGRFeatureDefn::AddGeomFieldDefn().
     805             :  *
     806             :  * @param hDefn handle to the feature definition to add the geometry field
     807             :  * definition to.
     808             :  * @param hNewGeomField handle to the new field definition.
     809             :  *
     810             :  * @since GDAL 1.11
     811             :  */
     812             : 
     813          11 : void OGR_FD_AddGeomFieldDefn(OGRFeatureDefnH hDefn,
     814             :                              OGRGeomFieldDefnH hNewGeomField)
     815             : 
     816             : {
     817          22 :     OGRFeatureDefn::FromHandle(hDefn)->AddGeomFieldDefn(
     818          11 :         OGRGeomFieldDefn::FromHandle(hNewGeomField));
     819          11 : }
     820             : 
     821             : /************************************************************************/
     822             : /*                         DeleteGeomFieldDefn()                        */
     823             : /************************************************************************/
     824             : 
     825             : /**
     826             :  * \brief Delete an existing geometry field definition.
     827             :  *
     828             :  * To delete an existing field definition from a layer definition, do not use
     829             :  * this function directly, but use OGRLayer::DeleteGeomField() instead.
     830             :  *
     831             :  * This method should only be called while there are no OGRFeature
     832             :  * objects in existence based on this OGRFeatureDefn.
     833             :  *
     834             :  * This method is the same as the C function OGR_FD_DeleteGeomFieldDefn().
     835             :  *
     836             :  * @param iGeomField the index of the geometry field definition.
     837             :  * @return OGRERR_NONE in case of success.
     838             :  *
     839             :  * @since GDAL 1.11
     840             :  */
     841             : 
     842       51527 : OGRErr OGRFeatureDefn::DeleteGeomFieldDefn(int iGeomField)
     843             : 
     844             : {
     845       51527 :     if (m_bSealed)
     846             :     {
     847           1 :         CPLError(CE_Failure, CPLE_AppDefined,
     848             :                  "OGRFeatureDefn::DeleteGeomFieldDefn() not allowed on a "
     849             :                  "sealed object");
     850           1 :         return OGRERR_FAILURE;
     851             :     }
     852       51526 :     if (iGeomField < 0 || iGeomField >= GetGeomFieldCount())
     853           2 :         return OGRERR_FAILURE;
     854             : 
     855       51524 :     apoGeomFieldDefn.erase(apoGeomFieldDefn.begin() + iGeomField);
     856       51524 :     return OGRERR_NONE;
     857             : }
     858             : 
     859             : /************************************************************************/
     860             : /*                     OGR_FD_DeleteGeomFieldDefn()                     */
     861             : /************************************************************************/
     862             : 
     863             : /**
     864             :  * \brief Delete an existing geometry field definition.
     865             :  *
     866             :  * To delete an existing geometry field definition from a layer definition, do
     867             :  * not use this function directly, but use OGR_L_DeleteGeomField() instead
     868             :  * (*not implemented yet*).
     869             :  *
     870             :  * This method should only be called while there are no OGRFeature
     871             :  * objects in existence based on this OGRFeatureDefn.
     872             :  *
     873             :  * This method is the same as the C++ method
     874             :  * OGRFeatureDefn::DeleteGeomFieldDefn().
     875             :  *
     876             :  * @param hDefn handle to the feature definition.
     877             :  * @param iGeomField the index of the geometry field definition.
     878             :  * @return OGRERR_NONE in case of success.
     879             :  *
     880             :  * @since GDAL 1.11
     881             :  */
     882             : 
     883           4 : OGRErr OGR_FD_DeleteGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField)
     884             : 
     885             : {
     886           4 :     return OGRFeatureDefn::FromHandle(hDefn)->DeleteGeomFieldDefn(iGeomField);
     887             : }
     888             : 
     889             : /************************************************************************/
     890             : /*                         GetGeomFieldIndex()                          */
     891             : /************************************************************************/
     892             : 
     893             : /**
     894             :  * \brief Find geometry field by name.
     895             :  *
     896             :  * The geometry field index of the first geometry field matching the passed
     897             :  * field name (case insensitively) is returned.
     898             :  *
     899             :  * This method is the same as the C function OGR_FD_GetGeomFieldIndex().
     900             :  *
     901             :  * @param pszGeomFieldName the geometry field name to search for.
     902             :  *
     903             :  * @return the geometry field index, or -1 if no match found.
     904             :  */
     905             : 
     906       26136 : int OGRFeatureDefn::GetGeomFieldIndex(const char *pszGeomFieldName) const
     907             : 
     908             : {
     909       26136 :     const int nGeomFieldCount = GetGeomFieldCount();
     910       42892 :     for (int i = 0; i < nGeomFieldCount; i++)
     911             :     {
     912       34526 :         const OGRGeomFieldDefn *poGFldDefn = GetGeomFieldDefn(i);
     913       69052 :         if (poGFldDefn != nullptr &&
     914       34526 :             EQUAL(pszGeomFieldName, poGFldDefn->GetNameRef()))
     915       17770 :             return i;
     916             :     }
     917             : 
     918        8366 :     return -1;
     919             : }
     920             : 
     921             : /************************************************************************/
     922             : /*                      OGR_FD_GetGeomFieldIndex()                      */
     923             : /************************************************************************/
     924             : /**
     925             :  * \brief Find geometry field by name.
     926             :  *
     927             :  * The geometry field index of the first geometry field matching the passed
     928             :  * field name (case insensitively) is returned.
     929             :  *
     930             :  * This function is the same as the C++ method
     931             :  * OGRFeatureDefn::GetGeomFieldIndex.
     932             :  *
     933             :  * @param hDefn handle to the feature definition to get field index from.
     934             :  * @param pszGeomFieldName the geometry field name to search for.
     935             :  *
     936             :  * @return the geometry field index, or -1 if no match found.
     937             :  */
     938             : 
     939          37 : int OGR_FD_GetGeomFieldIndex(OGRFeatureDefnH hDefn,
     940             :                              const char *pszGeomFieldName)
     941             : 
     942             : {
     943             : #ifdef OGRAPISPY_ENABLED
     944          37 :     if (bOGRAPISpyEnabled)
     945           2 :         OGRAPISpy_FD_GetGeomFieldIndex(hDefn, pszGeomFieldName);
     946             : #endif
     947             : 
     948          74 :     return OGRFeatureDefn::FromHandle(hDefn)->GetGeomFieldIndex(
     949          37 :         pszGeomFieldName);
     950             : }
     951             : 
     952             : /************************************************************************/
     953             : /*                            GetGeomType()                             */
     954             : /************************************************************************/
     955             : 
     956             : /**
     957             :  * \fn OGRwkbGeometryType OGRFeatureDefn::GetGeomType() const;
     958             :  *
     959             :  * \brief Fetch the geometry base type.
     960             :  *
     961             :  * Note that some drivers are unable to determine a specific geometry
     962             :  * type for a layer, in which case wkbUnknown is returned.  A value of
     963             :  * wkbNone indicates no geometry is available for the layer at all.
     964             :  * Many drivers do not properly mark the geometry
     965             :  * type as 25D even if some or all geometries are in fact 25D.  A few (broken)
     966             :  * drivers return wkbPolygon for layers that also include wkbMultiPolygon.
     967             :  *
     968             :  * Starting with GDAL 1.11, this method returns GetGeomFieldDefn(0)->GetType().
     969             :  *
     970             :  * This method is the same as the C function OGR_FD_GetGeomType().
     971             :  *
     972             :  * @return the base type for all geometry related to this definition.
     973             :  */
     974      550452 : OGRwkbGeometryType OGRFeatureDefn::GetGeomType() const
     975             : {
     976      550452 :     if (GetGeomFieldCount() == 0)
     977        1986 :         return wkbNone;
     978      548466 :     const OGRGeomFieldDefn *poGFldDefn = GetGeomFieldDefn(0);
     979      548466 :     if (poGFldDefn == nullptr)
     980           0 :         return wkbNone;
     981      548466 :     OGRwkbGeometryType eType = poGFldDefn->GetType();
     982      548471 :     if (eType == (/*wkbUnknown |*/ wkb25DBitInternalUse) &&
     983           5 :         CPLTestBool(CPLGetConfigOption("QGIS_HACK", "NO")))
     984           0 :         eType = wkbUnknown;
     985      548466 :     return eType;
     986             : }
     987             : 
     988             : /************************************************************************/
     989             : /*                         OGR_FD_GetGeomType()                         */
     990             : /************************************************************************/
     991             : /**
     992             :  * \brief Fetch the geometry base type of the passed feature definition.
     993             :  *
     994             :  * This function is the same as the C++ method OGRFeatureDefn::GetGeomType().
     995             :  *
     996             :  * Starting with GDAL 1.11, this method returns GetGeomFieldDefn(0)->GetType().
     997             :  *
     998             :  * @param hDefn handle to the feature definition to get the geometry type from.
     999             :  * @return the base type for all geometry related to this definition.
    1000             :  */
    1001             : 
    1002        2270 : OGRwkbGeometryType OGR_FD_GetGeomType(OGRFeatureDefnH hDefn)
    1003             : 
    1004             : {
    1005        2270 :     OGRwkbGeometryType eType = OGRFeatureDefn::FromHandle(hDefn)->GetGeomType();
    1006        2270 :     if (OGR_GT_IsNonLinear(eType) && !OGRGetNonLinearGeometriesEnabledFlag())
    1007             :     {
    1008           1 :         eType = OGR_GT_GetLinear(eType);
    1009             :     }
    1010             : #ifdef OGRAPISPY_ENABLED
    1011        2270 :     if (bOGRAPISpyEnabled)
    1012           2 :         OGRAPISpy_FD_GetGeomType(hDefn);
    1013             : #endif
    1014             : 
    1015        2270 :     return eType;
    1016             : }
    1017             : 
    1018             : /************************************************************************/
    1019             : /*                            SetGeomType()                             */
    1020             : /************************************************************************/
    1021             : 
    1022             : /**
    1023             :  * \brief Assign the base geometry type for this layer.
    1024             :  *
    1025             :  * All geometry objects using this type must be of the defined type or
    1026             :  * a derived type.  The default upon creation is wkbUnknown which allows for
    1027             :  * any geometry type.  The geometry type should generally not be changed
    1028             :  * after any OGRFeatures have been created against this definition.
    1029             :  *
    1030             :  * This method is the same as the C function OGR_FD_SetGeomType().
    1031             :  *
    1032             :  * Starting with GDAL 1.11, this method calls GetGeomFieldDefn(0)->SetType().
    1033             :  *
    1034             :  * @param eNewType the new type to assign.
    1035             :  */
    1036             : 
    1037       72336 : void OGRFeatureDefn::SetGeomType(OGRwkbGeometryType eNewType)
    1038             : 
    1039             : {
    1040       72336 :     if (m_bSealed)
    1041             :     {
    1042           0 :         CPLError(
    1043             :             CE_Failure, CPLE_AppDefined,
    1044             :             "OGRFeatureDefn::SetGeomType() not allowed on a sealed object");
    1045           0 :         return;
    1046             :     }
    1047       72336 :     const int nGeomFieldCount = GetGeomFieldCount();
    1048       72336 :     if (nGeomFieldCount > 0)
    1049             :     {
    1050       66958 :         if (nGeomFieldCount == 1 && eNewType == wkbNone)
    1051       50200 :             DeleteGeomFieldDefn(0);
    1052             :         else
    1053       16758 :             GetGeomFieldDefn(0)->SetType(eNewType);
    1054             :     }
    1055        5378 :     else if (eNewType != wkbNone)
    1056             :     {
    1057        3330 :         OGRGeomFieldDefn oGeomFieldDefn("", eNewType);
    1058        1665 :         AddGeomFieldDefn(&oGeomFieldDefn);
    1059             :     }
    1060             : }
    1061             : 
    1062             : /************************************************************************/
    1063             : /*                         OGR_FD_SetGeomType()                         */
    1064             : /************************************************************************/
    1065             : 
    1066             : /**
    1067             :  * \brief Assign the base geometry type for the passed layer (the same as the
    1068             :  * feature definition).
    1069             :  *
    1070             :  * All geometry objects using this type must be of the defined type or
    1071             :  * a derived type.  The default upon creation is wkbUnknown which allows for
    1072             :  * any geometry type.  The geometry type should generally not be changed
    1073             :  * after any OGRFeatures have been created against this definition.
    1074             :  *
    1075             :  * This function is the same as the C++ method OGRFeatureDefn::SetGeomType().
    1076             :  *
    1077             :  * Starting with GDAL 1.11, this method calls GetGeomFieldDefn(0)->SetType().
    1078             :  *
    1079             :  * @param hDefn handle to the layer or feature definition to set the geometry
    1080             :  * type to.
    1081             :  * @param eType the new type to assign.
    1082             :  */
    1083             : 
    1084          19 : void OGR_FD_SetGeomType(OGRFeatureDefnH hDefn, OGRwkbGeometryType eType)
    1085             : 
    1086             : {
    1087          19 :     OGRFeatureDefn::FromHandle(hDefn)->SetGeomType(eType);
    1088          19 : }
    1089             : 
    1090             : /************************************************************************/
    1091             : /*                             Reference()                              */
    1092             : /************************************************************************/
    1093             : 
    1094             : /**
    1095             :  * \fn int OGRFeatureDefn::Reference();
    1096             :  *
    1097             :  * \brief Increments the reference count by one.
    1098             :  *
    1099             :  * The reference count is used keep track of the number of OGRFeature
    1100             :  * objects referencing this definition.
    1101             :  *
    1102             :  * This method is the same as the C function OGR_FD_Reference().
    1103             :  *
    1104             :  * @return the updated reference count.
    1105             :  */
    1106             : 
    1107             : /************************************************************************/
    1108             : /*                          OGR_FD_Reference()                          */
    1109             : /************************************************************************/
    1110             : /**
    1111             :  * \brief Increments the reference count by one.
    1112             :  *
    1113             :  * The reference count is used keep track of the number of OGRFeature
    1114             :  * objects referencing this definition.
    1115             :  *
    1116             :  * This function is the same as the C++ method OGRFeatureDefn::Reference().
    1117             :  *
    1118             :  * @param hDefn handle to the feature definition on witch OGRFeature are
    1119             :  * based on.
    1120             :  * @return the updated reference count.
    1121             :  */
    1122             : 
    1123      125469 : int OGR_FD_Reference(OGRFeatureDefnH hDefn)
    1124             : 
    1125             : {
    1126      125469 :     return OGRFeatureDefn::FromHandle(hDefn)->Reference();
    1127             : }
    1128             : 
    1129             : /************************************************************************/
    1130             : /*                            Dereference()                             */
    1131             : /************************************************************************/
    1132             : 
    1133             : /**
    1134             :  * \fn int OGRFeatureDefn::Dereference();
    1135             :  *
    1136             :  * \brief Decrements the reference count by one.
    1137             :  *
    1138             :  * This method is the same as the C function OGR_FD_Dereference().
    1139             :  *
    1140             :  * @return the updated reference count.
    1141             :  */
    1142             : 
    1143             : /************************************************************************/
    1144             : /*                         OGR_FD_Dereference()                         */
    1145             : /************************************************************************/
    1146             : 
    1147             : /**
    1148             :  * \brief Decrements the reference count by one.
    1149             :  *
    1150             :  * This function is the same as the C++ method OGRFeatureDefn::Dereference().
    1151             :  *
    1152             :  * @param hDefn handle to the feature definition on witch OGRFeature are
    1153             :  * based on.
    1154             :  * @return the updated reference count.
    1155             :  */
    1156             : 
    1157           0 : int OGR_FD_Dereference(OGRFeatureDefnH hDefn)
    1158             : 
    1159             : {
    1160           0 :     return OGRFeatureDefn::FromHandle(hDefn)->Dereference();
    1161             : }
    1162             : 
    1163             : /************************************************************************/
    1164             : /*                         GetReferenceCount()                          */
    1165             : /************************************************************************/
    1166             : 
    1167             : /**
    1168             :  * \fn int OGRFeatureDefn::GetReferenceCount();
    1169             :  *
    1170             :  * \brief Fetch current reference count.
    1171             :  *
    1172             :  * This method is the same as the C function OGR_FD_GetReferenceCount().
    1173             :  *
    1174             :  * @return the current reference count.
    1175             :  */
    1176             : 
    1177             : /************************************************************************/
    1178             : /*                      OGR_FD_GetReferenceCount()                      */
    1179             : /************************************************************************/
    1180             : 
    1181             : /**
    1182             :  * \brief Fetch current reference count.
    1183             :  *
    1184             :  * This function is the same as the C++ method
    1185             :  * OGRFeatureDefn::GetReferenceCount().
    1186             :  *
    1187             :  * @param hDefn handle to the feature definition on witch OGRFeature are
    1188             :  * based on.
    1189             :  * @return the current reference count.
    1190             :  */
    1191             : 
    1192           3 : int OGR_FD_GetReferenceCount(OGRFeatureDefnH hDefn)
    1193             : 
    1194             : {
    1195           3 :     return OGRFeatureDefn::FromHandle(hDefn)->GetReferenceCount();
    1196             : }
    1197             : 
    1198             : /************************************************************************/
    1199             : /*                           GetFieldIndex()                            */
    1200             : /************************************************************************/
    1201             : 
    1202             : /**
    1203             :  * \brief Find field by name.
    1204             :  *
    1205             :  * The field index of the first field matching the passed field name (case
    1206             :  * insensitively) is returned.
    1207             :  *
    1208             :  * This method is the same as the C function OGR_FD_GetFieldIndex().
    1209             :  *
    1210             :  * @param pszFieldName the field name to search for.
    1211             :  *
    1212             :  * @return the field index, or -1 if no match found.
    1213             :  */
    1214             : 
    1215     2516090 : int OGRFeatureDefn::GetFieldIndex(const char *pszFieldName) const
    1216             : 
    1217             : {
    1218     2516090 :     const int nFieldCount = GetFieldCount();
    1219    17795100 :     for (int i = 0; i < nFieldCount; i++)
    1220             :     {
    1221    17710300 :         const OGRFieldDefn *poFDefn = GetFieldDefn(i);
    1222    17710300 :         if (poFDefn != nullptr && EQUAL(pszFieldName, poFDefn->GetNameRef()))
    1223     2431350 :             return i;
    1224             :     }
    1225             : 
    1226       84743 :     return -1;
    1227             : }
    1228             : 
    1229             : /************************************************************************/
    1230             : /*                      GetFieldIndexCaseSensitive()                    */
    1231             : /************************************************************************/
    1232             : 
    1233             : /**
    1234             :  * \brief Find field by name, in a case sensitive way.
    1235             :  *
    1236             :  * The field index of the first field matching the passed field name is
    1237             :  * returned.
    1238             :  *
    1239             :  * @param pszFieldName the field name to search for.
    1240             :  *
    1241             :  * @return the field index, or -1 if no match found.
    1242             :  */
    1243             : 
    1244        9732 : int OGRFeatureDefn::GetFieldIndexCaseSensitive(const char *pszFieldName) const
    1245             : 
    1246             : {
    1247        9732 :     const int nFieldCount = GetFieldCount();
    1248       57710 :     for (int i = 0; i < nFieldCount; i++)
    1249             :     {
    1250       55987 :         const OGRFieldDefn *poFDefn = GetFieldDefn(i);
    1251      111974 :         if (poFDefn != nullptr &&
    1252       55987 :             strcmp(pszFieldName, poFDefn->GetNameRef()) == 0)
    1253             :         {
    1254        8009 :             return i;
    1255             :         }
    1256             :     }
    1257             : 
    1258        1723 :     return -1;
    1259             : }
    1260             : 
    1261             : /************************************************************************/
    1262             : /*                        OGR_FD_GetFieldIndex()                        */
    1263             : /************************************************************************/
    1264             : /**
    1265             :  * \brief Find field by name.
    1266             :  *
    1267             :  * The field index of the first field matching the passed field name (case
    1268             :  * insensitively) is returned.
    1269             :  *
    1270             :  * This function is the same as the C++ method OGRFeatureDefn::GetFieldIndex.
    1271             :  *
    1272             :  * @param hDefn handle to the feature definition to get field index from.
    1273             :  * @param pszFieldName the field name to search for.
    1274             :  *
    1275             :  * @return the field index, or -1 if no match found.
    1276             :  */
    1277             : 
    1278        1926 : int OGR_FD_GetFieldIndex(OGRFeatureDefnH hDefn, const char *pszFieldName)
    1279             : 
    1280             : {
    1281             : #ifdef OGRAPISPY_ENABLED
    1282        1926 :     if (bOGRAPISpyEnabled)
    1283           2 :         OGRAPISpy_FD_GetFieldIndex(hDefn, pszFieldName);
    1284             : #endif
    1285             : 
    1286        1926 :     return OGRFeatureDefn::FromHandle(hDefn)->GetFieldIndex(pszFieldName);
    1287             : }
    1288             : 
    1289             : /************************************************************************/
    1290             : /*                         IsGeometryIgnored()                          */
    1291             : /************************************************************************/
    1292             : 
    1293             : /**
    1294             :  * \fn int OGRFeatureDefn::IsGeometryIgnored() const;
    1295             :  *
    1296             :  * \brief Determine whether the geometry can be omitted when fetching features
    1297             :  *
    1298             :  * This method is the same as the C function OGR_FD_IsGeometryIgnored().
    1299             :  *
    1300             :  * Starting with GDAL 1.11, this method returns
    1301             :  * GetGeomFieldDefn(0)->IsIgnored().
    1302             :  *
    1303             :  * @return ignore state
    1304             :  */
    1305             : 
    1306       91306 : int OGRFeatureDefn::IsGeometryIgnored() const
    1307             : {
    1308       91306 :     if (GetGeomFieldCount() == 0)
    1309         183 :         return FALSE;
    1310       91123 :     const OGRGeomFieldDefn *poGFldDefn = GetGeomFieldDefn(0);
    1311       91123 :     if (poGFldDefn == nullptr)
    1312           0 :         return FALSE;
    1313       91123 :     return poGFldDefn->IsIgnored();
    1314             : }
    1315             : 
    1316             : /************************************************************************/
    1317             : /*                      OGR_FD_IsGeometryIgnored()                      */
    1318             : /************************************************************************/
    1319             : 
    1320             : /**
    1321             :  * \brief Determine whether the geometry can be omitted when fetching features
    1322             :  *
    1323             :  * This function is the same as the C++ method
    1324             :  * OGRFeatureDefn::IsGeometryIgnored().
    1325             :  *
    1326             :  * Starting with GDAL 1.11, this method returns
    1327             :  * GetGeomFieldDefn(0)->IsIgnored().
    1328             :  *
    1329             :  * @param hDefn handle to the feature definition on witch OGRFeature are
    1330             :  * based on.
    1331             :  * @return ignore state
    1332             :  */
    1333             : 
    1334           6 : int OGR_FD_IsGeometryIgnored(OGRFeatureDefnH hDefn)
    1335             : {
    1336           6 :     return OGRFeatureDefn::FromHandle(hDefn)->IsGeometryIgnored();
    1337             : }
    1338             : 
    1339             : /************************************************************************/
    1340             : /*                         SetGeometryIgnored()                         */
    1341             : /************************************************************************/
    1342             : 
    1343             : /**
    1344             :  * \fn void OGRFeatureDefn::SetGeometryIgnored( int bIgnore );
    1345             :  *
    1346             :  * \brief Set whether the geometry can be omitted when fetching features
    1347             :  *
    1348             :  * This method is the same as the C function OGR_FD_SetGeometryIgnored().
    1349             :  *
    1350             :  * Starting with GDAL 1.11, this method calls GetGeomFieldDefn(0)->SetIgnored().
    1351             :  *
    1352             :  * @param bIgnore ignore state
    1353             :  */
    1354             : 
    1355         963 : void OGRFeatureDefn::SetGeometryIgnored(int bIgnore)
    1356             : {
    1357         963 :     if (GetGeomFieldCount() > 0)
    1358             :     {
    1359         777 :         OGRGeomFieldDefn *poGFldDefn = GetGeomFieldDefn(0);
    1360         777 :         if (poGFldDefn != nullptr)
    1361         777 :             poGFldDefn->SetIgnored(bIgnore);
    1362             :     }
    1363         963 : }
    1364             : 
    1365             : /************************************************************************/
    1366             : /*                      OGR_FD_SetGeometryIgnored()                     */
    1367             : /************************************************************************/
    1368             : 
    1369             : /**
    1370             :  * \brief Set whether the geometry can be omitted when fetching features
    1371             :  *
    1372             :  * This function is the same as the C++ method
    1373             :  * OGRFeatureDefn::SetGeometryIgnored().
    1374             :  *
    1375             :  * Starting with GDAL 1.11, this method calls GetGeomFieldDefn(0)->SetIgnored().
    1376             :  *
    1377             :  * @param hDefn handle to the feature definition on witch OGRFeature are
    1378             :  * based on.
    1379             :  * @param bIgnore ignore state
    1380             :  */
    1381             : 
    1382           3 : void OGR_FD_SetGeometryIgnored(OGRFeatureDefnH hDefn, int bIgnore)
    1383             : {
    1384           3 :     OGRFeatureDefn::FromHandle(hDefn)->SetGeometryIgnored(bIgnore);
    1385           3 : }
    1386             : 
    1387             : /************************************************************************/
    1388             : /*                           IsStyleIgnored()                           */
    1389             : /************************************************************************/
    1390             : 
    1391             : /**
    1392             :  * \fn int OGRFeatureDefn::IsStyleIgnored() const;
    1393             :  *
    1394             :  * \brief Determine whether the style can be omitted when fetching features
    1395             :  *
    1396             :  * This method is the same as the C function OGR_FD_IsStyleIgnored().
    1397             :  *
    1398             :  * @return ignore state
    1399             :  */
    1400             : 
    1401             : /************************************************************************/
    1402             : /*                       OGR_FD_IsStyleIgnored()                        */
    1403             : /************************************************************************/
    1404             : 
    1405             : /**
    1406             :  * \brief Determine whether the style can be omitted when fetching features
    1407             :  *
    1408             :  * This function is the same as the C++ method
    1409             :  * OGRFeatureDefn::IsStyleIgnored().
    1410             :  *
    1411             :  * @param hDefn handle to the feature definition on which OGRFeature are
    1412             :  * based on.
    1413             :  * @return ignore state
    1414             :  */
    1415             : 
    1416           2 : int OGR_FD_IsStyleIgnored(OGRFeatureDefnH hDefn)
    1417             : {
    1418           2 :     return OGRFeatureDefn::FromHandle(hDefn)->IsStyleIgnored();
    1419             : }
    1420             : 
    1421             : /************************************************************************/
    1422             : /*                          SetStyleIgnored()                           */
    1423             : /************************************************************************/
    1424             : 
    1425             : /**
    1426             :  * \fn void OGRFeatureDefn::SetStyleIgnored( int bIgnore );
    1427             :  *
    1428             :  * \brief Set whether the style can be omitted when fetching features
    1429             :  *
    1430             :  * This method is the same as the C function OGR_FD_SetStyleIgnored().
    1431             :  *
    1432             :  * @param bIgnore ignore state
    1433             :  */
    1434             : 
    1435             : /************************************************************************/
    1436             : /*                       OGR_FD_SetStyleIgnored()                       */
    1437             : /************************************************************************/
    1438             : 
    1439             : /**
    1440             :  * \brief Set whether the style can be omitted when fetching features
    1441             :  *
    1442             :  * This function is the same as the C++ method
    1443             :  * OGRFeatureDefn::SetStyleIgnored().
    1444             :  *
    1445             :  * @param hDefn handle to the feature definition on witch OGRFeature are
    1446             :  * based on.
    1447             :  * @param bIgnore ignore state
    1448             :  */
    1449             : 
    1450           0 : void OGR_FD_SetStyleIgnored(OGRFeatureDefnH hDefn, int bIgnore)
    1451             : {
    1452           0 :     OGRFeatureDefn::FromHandle(hDefn)->SetStyleIgnored(CPL_TO_BOOL(bIgnore));
    1453           0 : }
    1454             : 
    1455             : /************************************************************************/
    1456             : /*                         CreateFeatureDefn()                          */
    1457             : /************************************************************************/
    1458             : 
    1459             : /** Create a new feature definition object.
    1460             :  * @param pszName name
    1461             :  * @return new feature definition object.
    1462             :  */
    1463           1 : OGRFeatureDefn *OGRFeatureDefn::CreateFeatureDefn(const char *pszName)
    1464             : 
    1465             : {
    1466           1 :     return new OGRFeatureDefn(pszName);
    1467             : }
    1468             : 
    1469             : /************************************************************************/
    1470             : /*                         DestroyFeatureDefn()                         */
    1471             : /************************************************************************/
    1472             : 
    1473             : /** Destroy a feature definition.
    1474             :  * @param poDefn feature definition.
    1475             :  */
    1476           7 : void OGRFeatureDefn::DestroyFeatureDefn(OGRFeatureDefn *poDefn)
    1477             : 
    1478             : {
    1479           7 :     delete poDefn;
    1480           7 : }
    1481             : 
    1482             : /************************************************************************/
    1483             : /*                             IsSame()                                 */
    1484             : /************************************************************************/
    1485             : 
    1486             : /**
    1487             :  * \brief Test if the feature definition is identical to the other one.
    1488             :  *
    1489             :  * @param poOtherFeatureDefn the other feature definition to compare to.
    1490             :  * @return TRUE if the feature definition is identical to the other one.
    1491             :  */
    1492             : 
    1493         420 : int OGRFeatureDefn::IsSame(const OGRFeatureDefn *poOtherFeatureDefn) const
    1494             : {
    1495         420 :     const int nFieldCount = GetFieldCount();
    1496         420 :     const int nGeomFieldCount = GetGeomFieldCount();
    1497         420 :     if (strcmp(GetName(), poOtherFeatureDefn->GetName()) == 0 &&
    1498         778 :         nFieldCount == poOtherFeatureDefn->GetFieldCount() &&
    1499         358 :         nGeomFieldCount == poOtherFeatureDefn->GetGeomFieldCount())
    1500             :     {
    1501         904 :         for (int i = 0; i < nFieldCount; i++)
    1502             :         {
    1503         619 :             const OGRFieldDefn *poFldDefn = GetFieldDefn(i);
    1504             :             const OGRFieldDefn *poOtherFldDefn =
    1505         619 :                 poOtherFeatureDefn->GetFieldDefn(i);
    1506         619 :             if (!poFldDefn->IsSame(poOtherFldDefn))
    1507             :             {
    1508           3 :                 return FALSE;
    1509             :             }
    1510             :         }
    1511         597 :         for (int i = 0; i < nGeomFieldCount; i++)
    1512             :         {
    1513         337 :             const OGRGeomFieldDefn *poGFldDefn = GetGeomFieldDefn(i);
    1514             :             const OGRGeomFieldDefn *poOtherGFldDefn =
    1515         337 :                 poOtherFeatureDefn->GetGeomFieldDefn(i);
    1516         337 :             if (!poGFldDefn->IsSame(poOtherGFldDefn))
    1517             :             {
    1518          25 :                 return FALSE;
    1519             :             }
    1520             :         }
    1521         260 :         return TRUE;
    1522             :     }
    1523         132 :     return FALSE;
    1524             : }
    1525             : 
    1526             : /************************************************************************/
    1527             : /*                           OGR_FD_IsSame()                            */
    1528             : /************************************************************************/
    1529             : 
    1530             : /**
    1531             :  * \brief Test if the feature definition is identical to the other one.
    1532             :  *
    1533             :  * @param hFDefn handle to the feature definition on witch OGRFeature are
    1534             :  * based on.
    1535             :  * @param hOtherFDefn handle to the other feature definition to compare to.
    1536             :  * @return TRUE if the feature definition is identical to the other one.
    1537             :  *
    1538             :  * @since OGR 1.11
    1539             :  */
    1540             : 
    1541          11 : int OGR_FD_IsSame(OGRFeatureDefnH hFDefn, OGRFeatureDefnH hOtherFDefn)
    1542             : {
    1543          11 :     VALIDATE_POINTER1(hFDefn, "OGR_FD_IsSame", FALSE);
    1544          11 :     VALIDATE_POINTER1(hOtherFDefn, "OGR_FD_IsSame", FALSE);
    1545             : 
    1546          22 :     return OGRFeatureDefn::FromHandle(hFDefn)->IsSame(
    1547          11 :         OGRFeatureDefn::FromHandle(hOtherFDefn));
    1548             : }
    1549             : 
    1550             : /************************************************************************/
    1551             : /*                      ComputeMapForSetFrom()                          */
    1552             : /************************************************************************/
    1553             : 
    1554             : /**
    1555             :  * \brief Compute the map from source to target field that can be passed to
    1556             :  * SetFrom().
    1557             :  *
    1558             :  * @param poSrcFDefn the feature definition of source features later passed to
    1559             :  * SetFrom()
    1560             :  *
    1561             :  * @param bForgiving true if the operation should continue despite lacking
    1562             :  * output fields matching some of the source fields.
    1563             :  *
    1564             :  * @return an array of size poSrcFDefn->GetFieldCount() if everything succeeds,
    1565             :  * or empty in case a source field definition was not found in the target layer
    1566             :  * and bForgiving == true.
    1567             :  *
    1568             :  * @since GDAL 2.3
    1569             :  */
    1570             : 
    1571             : std::vector<int>
    1572        6354 : OGRFeatureDefn::ComputeMapForSetFrom(const OGRFeatureDefn *poSrcFDefn,
    1573             :                                      bool bForgiving) const
    1574             : {
    1575       12708 :     std::map<CPLString, int> oMapNameToTargetFieldIndex;
    1576       12708 :     std::map<CPLString, int> oMapNameToTargetFieldIndexUC;
    1577        6354 :     const int nFieldCount = GetFieldCount();
    1578       94825 :     for (int i = 0; i < nFieldCount; i++)
    1579             :     {
    1580       88471 :         const OGRFieldDefn *poFldDefn = GetFieldDefn(i);
    1581       88471 :         if (poFldDefn == nullptr)
    1582           0 :             continue;
    1583       88471 :         const char *pszName = poFldDefn->GetNameRef();
    1584             : 
    1585             :         // In the insane case where there are several matches, arbitrarily
    1586             :         // decide for the first one (preserve past behavior)
    1587       88471 :         if (oMapNameToTargetFieldIndex.find(pszName) ==
    1588      176942 :             oMapNameToTargetFieldIndex.end())
    1589             :         {
    1590       88471 :             oMapNameToTargetFieldIndex[pszName] = i;
    1591             :         }
    1592             :     }
    1593       12708 :     std::vector<int> aoMapSrcToTargetIdx;
    1594        6354 :     const int nSrcFieldCount = poSrcFDefn->GetFieldCount();
    1595        6354 :     aoMapSrcToTargetIdx.resize(nSrcFieldCount);
    1596       94018 :     for (int i = 0; i < nSrcFieldCount; i++)
    1597             :     {
    1598       87664 :         const OGRFieldDefn *poSrcFldDefn = poSrcFDefn->GetFieldDefn(i);
    1599       87664 :         if (poSrcFldDefn == nullptr)
    1600           0 :             continue;
    1601       87664 :         const char *pszSrcName = poSrcFldDefn->GetNameRef();
    1602             : 
    1603       87664 :         auto oIter = oMapNameToTargetFieldIndex.find(pszSrcName);
    1604       87664 :         if (oIter == oMapNameToTargetFieldIndex.end())
    1605             :         {
    1606             :             // Build case insensitive map only if needed
    1607        4954 :             if (oMapNameToTargetFieldIndexUC.empty())
    1608             :             {
    1609        6935 :                 for (int j = 0; j < nFieldCount; j++)
    1610             :                 {
    1611        5694 :                     const OGRFieldDefn *poFldDefn = GetFieldDefn(j);
    1612        5694 :                     if (poFldDefn == nullptr)
    1613           0 :                         continue;
    1614             :                     oMapNameToTargetFieldIndexUC
    1615        5694 :                         [CPLString(poFldDefn->GetNameRef()).toupper()] = j;
    1616             :                 }
    1617             :             }
    1618             :             oIter = oMapNameToTargetFieldIndexUC.find(
    1619        4954 :                 CPLString(pszSrcName).toupper());
    1620        4954 :             if (oIter == oMapNameToTargetFieldIndexUC.end())
    1621             :             {
    1622        1846 :                 if (!bForgiving)
    1623             :                 {
    1624           0 :                     return std::vector<int>();
    1625             :                 }
    1626        1846 :                 aoMapSrcToTargetIdx[i] = -1;
    1627             :             }
    1628             :             else
    1629             :             {
    1630        3108 :                 aoMapSrcToTargetIdx[i] = oIter->second;
    1631             :             }
    1632             :         }
    1633             :         else
    1634             :         {
    1635       82710 :             aoMapSrcToTargetIdx[i] = oIter->second;
    1636             :         }
    1637             :     }
    1638        6354 :     return aoMapSrcToTargetIdx;
    1639             : }
    1640             : 
    1641             : /************************************************************************/
    1642             : /*                       OGRFeatureDefn::Seal()                         */
    1643             : /************************************************************************/
    1644             : 
    1645             : /** Seal a OGRFeatureDefn.
    1646             :  *
    1647             :  * A sealed OGRFeatureDefn can not be modified while it is sealed.
    1648             :  *
    1649             :  * This method also call OGRFieldDefn::Seal() and OGRGeomFieldDefn::Seal()
    1650             :  * on its fields and geometry fields.
    1651             :  *
    1652             :  * This method should only be called by driver implementations.
    1653             :  *
    1654             :  * @param bSealFields Whether fields and geometry fields should be sealed.
    1655             :  *                    This is generally desirabled, but in case of deferred
    1656             :  *                    resolution of them, this parameter should be set to false.
    1657             :  * @since GDAL 3.9
    1658             :  */
    1659       49286 : void OGRFeatureDefn::Seal(bool bSealFields)
    1660             : {
    1661       49286 :     if (m_bSealed)
    1662             :     {
    1663           1 :         CPLError(CE_Failure, CPLE_AppDefined,
    1664             :                  "OGRFeatureDefn::Seal(): the object is already sealed");
    1665           1 :         return;
    1666             :     }
    1667       49285 :     if (bSealFields)
    1668             :     {
    1669       37781 :         const int nFieldCount = GetFieldCount();
    1670     4745850 :         for (int i = 0; i < nFieldCount; ++i)
    1671     4708070 :             GetFieldDefn(i)->Seal();
    1672       37781 :         const int nGeomFieldCount = GetGeomFieldCount();
    1673       65558 :         for (int i = 0; i < nGeomFieldCount; ++i)
    1674       27777 :             GetGeomFieldDefn(i)->Seal();
    1675             :     }
    1676       49285 :     m_bSealed = true;
    1677             : }
    1678             : 
    1679             : /************************************************************************/
    1680             : /*                       OGRFeatureDefn::Unseal()                       */
    1681             : /************************************************************************/
    1682             : 
    1683             : /** Unseal a OGRFeatureDefn.
    1684             :  *
    1685             :  * Undo OGRFeatureDefn::Seal()
    1686             :  *
    1687             :  * This method also call OGRFieldDefn::Unseal() and OGRGeomFieldDefn::Unseal()
    1688             :  * on its fields and geometry fields.
    1689             :  *
    1690             :  * Using GetTemporaryUnsealer() is recommended for most use cases.
    1691             :  *
    1692             :  * This method should only be called by driver implementations.
    1693             :  *
    1694             :  * @param bUnsealFields Whether fields and geometry fields should be unsealed.
    1695             :  *                      This is generally desirabled, but in case of deferred
    1696             :  *                      resolution of them, this parameter should be set to
    1697             :  * false.
    1698             :  * @since GDAL 3.9
    1699             :  */
    1700       25254 : void OGRFeatureDefn::Unseal(bool bUnsealFields)
    1701             : {
    1702       25254 :     if (!m_bSealed)
    1703             :     {
    1704           1 :         CPLError(CE_Failure, CPLE_AppDefined,
    1705             :                  "OGRFeatureDefn::Unseal(): the object is already unsealed");
    1706           1 :         return;
    1707             :     }
    1708       25253 :     m_bSealed = false;
    1709       25253 :     if (bUnsealFields)
    1710             :     {
    1711       25208 :         const int nFieldCount = GetFieldCount();
    1712     4696740 :         for (int i = 0; i < nFieldCount; ++i)
    1713     4671530 :             GetFieldDefn(i)->Unseal();
    1714       25208 :         const int nGeomFieldCount = GetGeomFieldCount();
    1715       41801 :         for (int i = 0; i < nGeomFieldCount; ++i)
    1716       16593 :             GetGeomFieldDefn(i)->Unseal();
    1717             :     }
    1718             : }
    1719             : 
    1720             : /************************************************************************/
    1721             : /*                  OGRFeatureDefn::GetTemporaryUnsealer()              */
    1722             : /************************************************************************/
    1723             : 
    1724             : /** Return an object that temporary unseals the OGRFeatureDefn
    1725             :  *
    1726             :  * The returned object calls Unseal() initially, and when it is destroyed
    1727             :  * it calls Seal().
    1728             :  * This method should be called on a OGRFeatureDefn that has been sealed
    1729             :  * previously.
    1730             :  * GetTemporaryUnsealer() calls may be nested, in which case only the first
    1731             :  * one has an effect (similarly to a recursive mutex locked in a nested way
    1732             :  * from the same thread).
    1733             :  *
    1734             :  * This method should only be called by driver implementations.
    1735             :  *
    1736             :  * It is also possible to use the helper method whileUnsealing(). Example:
    1737             :  * whileUnsealing(poFeatureDefn)->some_method()
    1738             :  *
    1739             :  * @param bSealFields Whether fields and geometry fields should be unsealed and
    1740             :  *                    resealed.
    1741             :  *                    This is generally desirabled, but in case of deferred
    1742             :  *                    resolution of them, this parameter should be set to false.
    1743             :  * @since GDAL 3.9
    1744             :  */
    1745             : OGRFeatureDefn::TemporaryUnsealer
    1746       25256 : OGRFeatureDefn::GetTemporaryUnsealer(bool bSealFields)
    1747             : {
    1748       25256 :     return TemporaryUnsealer(this, bSealFields);
    1749             : }
    1750             : 
    1751             : /*! @cond Doxygen_Suppress */
    1752             : 
    1753             : /************************************************************************/
    1754             : /*                TemporaryUnsealer::TemporaryUnsealer()                */
    1755             : /************************************************************************/
    1756             : 
    1757       25256 : OGRFeatureDefn::TemporaryUnsealer::TemporaryUnsealer(
    1758       25256 :     OGRFeatureDefn *poFeatureDefn, bool bSealFields)
    1759       25256 :     : m_poFeatureDefn(poFeatureDefn), m_bSealFields(bSealFields)
    1760             : {
    1761       25256 :     if (m_poFeatureDefn->m_nTemporaryUnsealCount == 0)
    1762             :     {
    1763       25254 :         if (m_poFeatureDefn->m_bSealed)
    1764             :         {
    1765       25253 :             m_poFeatureDefn->Unseal(m_bSealFields);
    1766       25253 :             m_poFeatureDefn->m_nTemporaryUnsealCount = 1;
    1767             :         }
    1768             :         else
    1769             :         {
    1770           1 :             CPLError(CE_Warning, CPLE_AppDefined,
    1771             :                      "OGRFeatureDefn::GetTemporaryUnsealer() called on "
    1772             :                      "a unsealed object");
    1773           1 :             m_poFeatureDefn->m_nTemporaryUnsealCount = -1;
    1774             :         }
    1775             :     }
    1776           2 :     else if (m_poFeatureDefn->m_nTemporaryUnsealCount > 0)
    1777             :     {
    1778             :         // m_poFeatureDefn is already under an active TemporaryUnsealer.
    1779             :         // Just increment the counter
    1780           1 :         ++m_poFeatureDefn->m_nTemporaryUnsealCount;
    1781             :     }
    1782             :     else
    1783             :     {
    1784             :         // m_poFeatureDefn is already under a misused TemporaryUnsealer.
    1785             :         // Decrement again the counter
    1786           1 :         --m_poFeatureDefn->m_nTemporaryUnsealCount;
    1787             :     }
    1788       25256 : }
    1789             : 
    1790             : /************************************************************************/
    1791             : /*                TemporaryUnsealer::~TemporaryUnsealer()               */
    1792             : /************************************************************************/
    1793             : 
    1794       50512 : OGRFeatureDefn::TemporaryUnsealer::~TemporaryUnsealer()
    1795             : {
    1796       25256 :     if (m_poFeatureDefn->m_nTemporaryUnsealCount > 0)
    1797             :     {
    1798             :         // m_poFeatureDefn is already under an active TemporaryUnsealer.
    1799             :         // Decrement increment the counter and unseal when it reaches 0
    1800       25254 :         --m_poFeatureDefn->m_nTemporaryUnsealCount;
    1801       25254 :         if (m_poFeatureDefn->m_nTemporaryUnsealCount == 0)
    1802             :         {
    1803       25253 :             if (!m_poFeatureDefn->m_bSealed)
    1804             :             {
    1805       25253 :                 m_poFeatureDefn->Seal(m_bSealFields);
    1806             :             }
    1807             :             else
    1808             :             {
    1809           0 :                 CPLError(
    1810             :                     CE_Failure, CPLE_AppDefined,
    1811             :                     "Misuse of sealing functionality. "
    1812             :                     "OGRFeatureDefn::TemporaryUnsealer::~TemporaryUnsealer() "
    1813             :                     "claled on a sealed object");
    1814             :             }
    1815             :         }
    1816             :     }
    1817             :     else
    1818             :     {
    1819             :         // m_poFeatureDefn is already under a misused TemporaryUnsealer.
    1820             :         // Increment the counter
    1821           2 :         CPLAssert(m_poFeatureDefn->m_nTemporaryUnsealCount < 0);
    1822           2 :         ++m_poFeatureDefn->m_nTemporaryUnsealCount;
    1823             :     }
    1824       25256 : }
    1825             : 
    1826             : /*! @endcond */

Generated by: LCOV version 1.14