LCOV - code coverage report
Current view: top level - ogr - ogrfeaturedefn.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 334 376 88.8 %
Date: 2026-03-17 00:06:02 Functions: 57 64 89.1 %

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

Generated by: LCOV version 1.14