LCOV - code coverage report
Current view: top level - ogr - ogrfeature.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 2531 2781 91.0 %
Date: 2025-10-17 14:31:27 Functions: 195 210 92.9 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  The OGRFeature class implementation.
       5             :  * Author:   Frank Warmerdam, warmerda@home.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
       9             :  * Copyright (c) 2008-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_api.h"
      16             : #include "ogr_feature.h"
      17             : 
      18             : #include <cerrno>
      19             : #include <cinttypes>
      20             : #include <climits>
      21             : #include <cstdio>
      22             : #include <cstdlib>
      23             : #include <cstring>
      24             : #include <cmath>
      25             : #include <ctime>
      26             : 
      27             : #include <algorithm>
      28             : #include <limits>
      29             : #include <map>
      30             : #include <new>
      31             : #include <vector>
      32             : 
      33             : #include "cpl_conv.h"
      34             : #include "cpl_error.h"
      35             : #include "cpl_string.h"
      36             : #include "cpl_time.h"
      37             : #include "cpl_vsi.h"
      38             : #include "ogr_core.h"
      39             : #include "ogr_featurestyle.h"
      40             : #include "ogr_geometry.h"
      41             : #include "ogr_p.h"
      42             : #include "ogrlibjsonutils.h"
      43             : 
      44             : #include "cpl_json_header.h"
      45             : 
      46             : // Too many false positives from gcc 13.2.1 in that file...
      47             : #if defined(__GNUC__)
      48             : #pragma GCC diagnostic push
      49             : #pragma GCC diagnostic ignored "-Wnull-dereference"
      50             : #endif
      51             : 
      52             : /************************************************************************/
      53             : /*                             OGRFeature()                             */
      54             : /************************************************************************/
      55             : 
      56             : /**
      57             :  * \brief Constructor
      58             :  *
      59             :  * Note that the OGRFeature will increment the reference count of its
      60             :  * defining OGRFeatureDefn.  Destruction of the OGRFeatureDefn before
      61             :  * destruction of all OGRFeatures that depend on it is likely to result in
      62             :  * a crash.
      63             :  *
      64             :  * This method is the same as the C function OGR_F_Create().
      65             :  *
      66             :  * @param poDefnIn feature class (layer) definition to which the feature will
      67             :  * adhere.
      68             :  */
      69             : 
      70     2373550 : OGRFeature::OGRFeature(const OGRFeatureDefn *poDefnIn)
      71             :     : nFID(OGRNullFID), poDefn(poDefnIn), papoGeometries(nullptr),
      72             :       pauFields(nullptr), m_pszNativeData(nullptr),
      73             :       m_pszNativeMediaType(nullptr), m_pszStyleString(nullptr),
      74     2373550 :       m_poStyleTable(nullptr), m_pszTmpFieldValue(nullptr)
      75             : {
      76     2373550 :     const_cast<OGRFeatureDefn *>(poDefnIn)->Reference();
      77             : 
      78     2373550 :     const int nFieldCount = poDefn->GetFieldCount();
      79     2373550 :     pauFields = static_cast<OGRField *>(
      80     2373550 :         VSI_MALLOC_VERBOSE(nFieldCount * sizeof(OGRField)));
      81             : 
      82     2373550 :     papoGeometries = static_cast<OGRGeometry **>(
      83     2373550 :         VSI_CALLOC_VERBOSE(poDefn->GetGeomFieldCount(), sizeof(OGRGeometry *)));
      84             : 
      85             :     // Initialize array to the unset special value.
      86     2373550 :     if (pauFields != nullptr)
      87             :     {
      88    13276200 :         for (int i = 0; i < nFieldCount; i++)
      89             :         {
      90    10902600 :             pauFields[i].Set.nMarker1 = OGRUnsetMarker;
      91    10902600 :             pauFields[i].Set.nMarker2 = OGRUnsetMarker;
      92    10902600 :             pauFields[i].Set.nMarker3 = OGRUnsetMarker;
      93             :         }
      94             :     }
      95     2373550 : }
      96             : 
      97             : /************************************************************************/
      98             : /*                            OGR_F_Create()                            */
      99             : /************************************************************************/
     100             : /**
     101             :  * \brief Feature factory.
     102             :  *
     103             :  * Note that the OGRFeature will increment the reference count of its
     104             :  * defining OGRFeatureDefn.  Destruction of the OGRFeatureDefn before
     105             :  * destruction of all OGRFeatures that depend on it is likely to result in
     106             :  * a crash.
     107             :  *
     108             :  * This function is the same as the C++ method OGRFeature::OGRFeature().
     109             :  *
     110             :  * @param hDefn handle to the feature class (layer) definition to
     111             :  * which the feature will adhere.
     112             :  *
     113             :  * @return a handle to the new feature object with null fields and no geometry,
     114             :  * or, NULL in case out of memory situation.
     115             :  */
     116             : 
     117      126544 : OGRFeatureH OGR_F_Create(OGRFeatureDefnH hDefn)
     118             : 
     119             : {
     120      126544 :     VALIDATE_POINTER1(hDefn, "OGR_F_Create", nullptr);
     121      126544 :     return OGRFeature::ToHandle(
     122      253088 :         OGRFeature::CreateFeature(OGRFeatureDefn::FromHandle(hDefn)));
     123             : }
     124             : 
     125             : /************************************************************************/
     126             : /*                            ~OGRFeature()                             */
     127             : /************************************************************************/
     128             : 
     129     6553540 : OGRFeature::~OGRFeature()
     130             : 
     131             : {
     132     2373520 :     if (pauFields != nullptr)
     133             :     {
     134             :         // We can call GetFieldCountUnsafe() as the constructor has called
     135             :         // the regular GetFieldCount()
     136     2373520 :         const int nFieldcount = poDefn->GetFieldCountUnsafe();
     137    13276600 :         for (int i = 0; i < nFieldcount; i++)
     138             :         {
     139    10903100 :             const OGRFieldDefn *poFDefn = poDefn->GetFieldDefnUnsafe(i);
     140             : 
     141    10903100 :             if (!IsFieldSetAndNotNullUnsafe(i))
     142     3410530 :                 continue;
     143             : 
     144     7492570 :             switch (poFDefn->GetType())
     145             :             {
     146     4057190 :                 case OFTString:
     147     4057190 :                     if (pauFields[i].String != nullptr)
     148     4057090 :                         VSIFree(pauFields[i].String);
     149     4057190 :                     break;
     150             : 
     151       58663 :                 case OFTBinary:
     152       58663 :                     if (pauFields[i].Binary.paData != nullptr)
     153       58662 :                         VSIFree(pauFields[i].Binary.paData);
     154       58663 :                     break;
     155             : 
     156       23735 :                 case OFTStringList:
     157       23735 :                     CSLDestroy(pauFields[i].StringList.paList);
     158       23735 :                     break;
     159             : 
     160       81147 :                 case OFTIntegerList:
     161             :                 case OFTInteger64List:
     162             :                 case OFTRealList:
     163       81147 :                     CPLFree(pauFields[i].IntegerList.paList);
     164       81147 :                     break;
     165             : 
     166     3271830 :                 default:
     167             :                     // TODO(schwehr): Add support for wide strings.
     168     3271830 :                     break;
     169             :             }
     170             :         }
     171             :     }
     172             : 
     173     2373520 :     if (papoGeometries != nullptr)
     174             :     {
     175     2373520 :         const int nGeomFieldCount = poDefn->GetGeomFieldCount();
     176             : 
     177     4002930 :         for (int i = 0; i < nGeomFieldCount; i++)
     178             :         {
     179     1629410 :             delete papoGeometries[i];
     180             :         }
     181             :     }
     182             : 
     183     2373520 :     if (poDefn)
     184     2373520 :         const_cast<OGRFeatureDefn *>(poDefn)->Release();
     185             : 
     186     2373520 :     CPLFree(pauFields);
     187     2373520 :     CPLFree(papoGeometries);
     188     2373520 :     CPLFree(m_pszStyleString);
     189     2373520 :     CPLFree(m_pszTmpFieldValue);
     190     2373520 :     CPLFree(m_pszNativeData);
     191     2373520 :     CPLFree(m_pszNativeMediaType);
     192     4180020 : }
     193             : 
     194             : /************************************************************************/
     195             : /*                           OGR_F_Destroy()                            */
     196             : /************************************************************************/
     197             : /**
     198             :  * \brief Destroy feature
     199             :  *
     200             :  * The feature is deleted, but within the context of the GDAL/OGR heap.
     201             :  * This is necessary when higher level applications use GDAL/OGR from a
     202             :  * DLL and they want to delete a feature created within the DLL.  If the
     203             :  * delete is done in the calling application the memory will be freed onto
     204             :  * the application heap which is inappropriate.
     205             :  *
     206             :  * This function is the same as the C++ method OGRFeature::DestroyFeature().
     207             :  *
     208             :  * @param hFeat handle to the feature to destroy.
     209             :  */
     210             : 
     211      211726 : void OGR_F_Destroy(OGRFeatureH hFeat)
     212             : 
     213             : {
     214      211726 :     delete OGRFeature::FromHandle(hFeat);
     215      211726 : }
     216             : 
     217             : /************************************************************************/
     218             : /*                           CreateFeature()                            */
     219             : /************************************************************************/
     220             : 
     221             : /**
     222             :  * \brief Feature factory.
     223             :  *
     224             :  * This is essentially a feature factory, useful for
     225             :  * applications creating features but wanting to ensure they
     226             :  * are created out of the OGR/GDAL heap.
     227             :  *
     228             :  * This method is the same as the C function OGR_F_Create().
     229             :  *
     230             :  * @param poDefn Feature definition defining schema.
     231             :  *
     232             :  * @return new feature object with null fields and no geometry, or
     233             :  * NULL in case of out of memory situation.  May be deleted with
     234             :  * DestroyFeature().
     235             :  */
     236             : 
     237      799716 : OGRFeature *OGRFeature::CreateFeature(const OGRFeatureDefn *poDefn)
     238             : 
     239             : {
     240      799716 :     OGRFeature *poFeature = new (std::nothrow) OGRFeature(poDefn);
     241      799716 :     if (poFeature == nullptr)
     242           0 :         return nullptr;
     243             : 
     244           0 :     if ((poFeature->pauFields == nullptr &&
     245     1599430 :          poDefn->GetFieldCountUnsafe() != 0) ||
     246      799716 :         (poFeature->papoGeometries == nullptr &&
     247           0 :          poDefn->GetGeomFieldCount() != 0))
     248             :     {
     249           0 :         delete poFeature;
     250           0 :         return nullptr;
     251             :     }
     252             : 
     253      799716 :     return poFeature;
     254             : }
     255             : 
     256             : /************************************************************************/
     257             : /*                           DestroyFeature()                           */
     258             : /************************************************************************/
     259             : 
     260             : /**
     261             :  * \brief Destroy feature
     262             :  *
     263             :  * The feature is deleted, but within the context of the GDAL/OGR heap.
     264             :  * This is necessary when higher level applications use GDAL/OGR from a
     265             :  * DLL and they want to delete a feature created within the DLL.  If the
     266             :  * delete is done in the calling application the memory will be freed onto
     267             :  * the application heap which is inappropriate.
     268             :  *
     269             :  * This method is the same as the C function OGR_F_Destroy().
     270             :  *
     271             :  * @param poFeature the feature to delete.
     272             :  */
     273             : 
     274       66253 : void OGRFeature::DestroyFeature(OGRFeature *poFeature)
     275             : 
     276             : {
     277       66253 :     delete poFeature;
     278       66253 : }
     279             : 
     280             : /************************************************************************/
     281             : /*                                Reset()                               */
     282             : /************************************************************************/
     283             : 
     284             : /** Reset the state of a OGRFeature to its state after construction.
     285             :  *
     286             :  * This enables recycling existing OGRFeature instances.
     287             :  *
     288             :  * @since GDAL 3.5
     289             :  */
     290        2720 : void OGRFeature::Reset()
     291             : {
     292        2720 :     nFID = OGRNullFID;
     293             : 
     294        2720 :     if (pauFields != nullptr)
     295             :     {
     296        2720 :         const int nFieldcount = poDefn->GetFieldCountUnsafe();
     297        9481 :         for (int i = 0; i < nFieldcount; i++)
     298             :         {
     299        6761 :             if (!IsFieldSetAndNotNullUnsafe(i))
     300        1396 :                 continue;
     301             : 
     302        5365 :             const OGRFieldDefn *poFDefn = poDefn->GetFieldDefnUnsafe(i);
     303        5365 :             switch (poFDefn->GetType())
     304             :             {
     305         434 :                 case OFTString:
     306         434 :                     if (pauFields[i].String != nullptr)
     307         434 :                         VSIFree(pauFields[i].String);
     308         434 :                     break;
     309             : 
     310         195 :                 case OFTBinary:
     311         195 :                     if (pauFields[i].Binary.paData != nullptr)
     312         195 :                         VSIFree(pauFields[i].Binary.paData);
     313         195 :                     break;
     314             : 
     315         142 :                 case OFTStringList:
     316         142 :                     CSLDestroy(pauFields[i].StringList.paList);
     317         142 :                     break;
     318             : 
     319         654 :                 case OFTIntegerList:
     320             :                 case OFTInteger64List:
     321             :                 case OFTRealList:
     322         654 :                     CPLFree(pauFields[i].IntegerList.paList);
     323         654 :                     break;
     324             : 
     325        3940 :                 default:
     326             :                     // TODO(schwehr): Add support for wide strings.
     327        3940 :                     break;
     328             :             }
     329             : 
     330        5365 :             pauFields[i].Set.nMarker1 = OGRUnsetMarker;
     331        5365 :             pauFields[i].Set.nMarker2 = OGRUnsetMarker;
     332        5365 :             pauFields[i].Set.nMarker3 = OGRUnsetMarker;
     333             :         }
     334             :     }
     335             : 
     336        2720 :     if (papoGeometries != nullptr)
     337             :     {
     338        2720 :         const int nGeomFieldCount = poDefn->GetGeomFieldCount();
     339             : 
     340        5334 :         for (int i = 0; i < nGeomFieldCount; i++)
     341             :         {
     342        2614 :             delete papoGeometries[i];
     343        2614 :             papoGeometries[i] = nullptr;
     344             :         }
     345             :     }
     346             : 
     347        2720 :     if (m_pszStyleString)
     348             :     {
     349           0 :         CPLFree(m_pszStyleString);
     350           0 :         m_pszStyleString = nullptr;
     351             :     }
     352             : 
     353        2720 :     if (m_pszNativeData)
     354             :     {
     355           0 :         CPLFree(m_pszNativeData);
     356           0 :         m_pszNativeData = nullptr;
     357             :     }
     358             : 
     359        2720 :     if (m_pszNativeMediaType)
     360             :     {
     361           0 :         CPLFree(m_pszNativeMediaType);
     362           0 :         m_pszNativeMediaType = nullptr;
     363             :     }
     364        2720 : }
     365             : 
     366             : /************************************************************************/
     367             : /*                        SetFDefnUnsafe()                              */
     368             : /************************************************************************/
     369             : 
     370             : //! @cond Doxygen_Suppress
     371       26445 : void OGRFeature::SetFDefnUnsafe(OGRFeatureDefn *poNewFDefn)
     372             : {
     373       26445 :     poNewFDefn->Reference();
     374       26445 :     const_cast<OGRFeatureDefn *>(poDefn)->Release();
     375       26445 :     poDefn = poNewFDefn;
     376       26445 : }
     377             : 
     378             : //! @endcond
     379             : 
     380             : /************************************************************************/
     381             : /*                             GetDefnRef()                             */
     382             : /************************************************************************/
     383             : 
     384             : /**
     385             :  * \fn OGRFeatureDefn *OGRFeature::GetDefnRef();
     386             :  *
     387             :  * \brief Fetch feature definition.
     388             :  *
     389             :  * This method is the same as the C function OGR_F_GetDefnRef().
     390             :  *
     391             :  * @return a reference to the feature definition object.
     392             :  */
     393             : 
     394             : /**
     395             :  * \fn const OGRFeatureDefn *OGRFeature::GetDefnRef() const;
     396             :  *
     397             :  * \brief Fetch feature definition.
     398             :  *
     399             :  * This method is the same as the C function OGR_F_GetDefnRef().
     400             :  *
     401             :  * @return a reference to the feature definition object.
     402             :  */
     403             : 
     404             : /************************************************************************/
     405             : /*                          OGR_F_GetDefnRef()                          */
     406             : /************************************************************************/
     407             : 
     408             : /**
     409             :  * \brief Fetch feature definition.
     410             :  *
     411             :  * This function is the same as the C++ method OGRFeature::GetDefnRef().
     412             :  *
     413             :  * @param hFeat handle to the feature to get the feature definition from.
     414             :  *
     415             :  * @return a handle to the feature definition object on which feature
     416             :  * depends.
     417             :  */
     418             : 
     419       46321 : OGRFeatureDefnH OGR_F_GetDefnRef(OGRFeatureH hFeat)
     420             : 
     421             : {
     422       46321 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetDefnRef", nullptr);
     423             : 
     424       46321 :     return OGRFeatureDefn::ToHandle(const_cast<OGRFeatureDefn *>(
     425       92642 :         OGRFeature::FromHandle(hFeat)->GetDefnRef()));
     426             : }
     427             : 
     428             : /************************************************************************/
     429             : /*                        SetGeometryDirectly()                         */
     430             : /************************************************************************/
     431             : 
     432             : /**
     433             :  * \brief Set feature geometry.
     434             :  *
     435             :  * This method updates the features geometry, and operates the same as
     436             :  * SetGeometry(), except that this method assumes ownership of the
     437             :  * passed geometry (even in case of failure of that function).
     438             :  *
     439             :  * This method is the same as the C function OGR_F_SetGeometryDirectly().
     440             :  *
     441             :  * @note This method has only an effect on the in-memory feature object. If
     442             :  * this object comes from a layer and the modifications must be serialized back
     443             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
     444             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
     445             :  *
     446             :  * @param poGeomIn new geometry to apply to feature. Passing NULL value here
     447             :  * is correct and it will result in deallocation of currently assigned geometry
     448             :  * without assigning new one.
     449             :  *
     450             :  * @return OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if
     451             :  * the geometry type is illegal for the OGRFeatureDefn (checking not yet
     452             :  * implemented).
     453             :  */
     454             : 
     455     1118470 : OGRErr OGRFeature::SetGeometryDirectly(OGRGeometry *poGeomIn)
     456             : 
     457             : {
     458     1118470 :     if (poGeomIn == GetGeometryRef())
     459             :     {
     460         872 :         return OGRERR_NONE;
     461             :     }
     462             : 
     463     1117600 :     return SetGeomField(0, std::unique_ptr<OGRGeometry>(poGeomIn));
     464             : }
     465             : 
     466             : /************************************************************************/
     467             : /*                     OGR_F_SetGeometryDirectly()                      */
     468             : /************************************************************************/
     469             : 
     470             : /**
     471             :  * \brief Set feature geometry.
     472             :  *
     473             :  * This function updates the features geometry, and operates the same as
     474             :  * SetGeometry(), except that this function assumes ownership of the
     475             :  * passed geometry (even in case of failure of that function).
     476             :  *
     477             :  * This function is the same as the C++ method
     478             :  * OGRFeature::SetGeometryDirectly.
     479             :  *
     480             :  * @note This method has only an effect on the in-memory feature object. If
     481             :  * this object comes from a layer and the modifications must be serialized back
     482             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
     483             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
     484             :  *
     485             :  * @param hFeat handle to the feature on which to apply the geometry.
     486             :  * @param hGeom handle to the new geometry to apply to feature.
     487             :  *
     488             :  * @return OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if
     489             :  * the geometry type is illegal for the OGRFeatureDefn (checking not yet
     490             :  * implemented).
     491             :  */
     492             : 
     493       38762 : OGRErr OGR_F_SetGeometryDirectly(OGRFeatureH hFeat, OGRGeometryH hGeom)
     494             : 
     495             : {
     496       38762 :     VALIDATE_POINTER1(hFeat, "OGR_F_SetGeometryDirectly", OGRERR_FAILURE);
     497             : 
     498       38762 :     return OGRFeature::FromHandle(hFeat)->SetGeometryDirectly(
     499       38762 :         OGRGeometry::FromHandle(hGeom));
     500             : }
     501             : 
     502             : /************************************************************************/
     503             : /*                            SetGeometry()                             */
     504             : /************************************************************************/
     505             : 
     506             : /**
     507             :  * \brief Set feature geometry.
     508             :  *
     509             :  * This method updates the features geometry, and operates the same as
     510             :  * SetGeometryDirectly(), except that this method does not assume ownership
     511             :  * of the passed geometry, but instead makes a copy of it.
     512             :  *
     513             :  * This method is the same as the C function OGR_F_SetGeometry().
     514             :  *
     515             :  * @note This method has only an effect on the in-memory feature object. If
     516             :  * this object comes from a layer and the modifications must be serialized back
     517             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
     518             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
     519             :  *
     520             :  * @param poGeomIn new geometry to apply to feature. Passing NULL value here
     521             :  * is correct and it will result in deallocation of currently assigned geometry
     522             :  * without assigning new one.
     523             :  *
     524             :  * @return OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if
     525             :  * the geometry type is illegal for the OGRFeatureDefn (checking not yet
     526             :  * implemented).
     527             :  */
     528             : 
     529      236585 : OGRErr OGRFeature::SetGeometry(const OGRGeometry *poGeomIn)
     530             : 
     531             : {
     532      236585 :     if (GetGeomFieldCount() < 1)
     533           2 :         return OGRERR_FAILURE;
     534             : 
     535      236583 :     return SetGeomField(0, poGeomIn);
     536             : }
     537             : 
     538             : /************************************************************************/
     539             : /*                         OGR_F_SetGeometry()                          */
     540             : /************************************************************************/
     541             : 
     542             : /**
     543             :  * \brief Set feature geometry.
     544             :  *
     545             :  * This function updates the features geometry, and operates the same as
     546             :  * SetGeometryDirectly(), except that this function does not assume ownership
     547             :  * of the passed geometry, but instead makes a copy of it.
     548             :  *
     549             :  * This function is the same as the C++ OGRFeature::SetGeometry().
     550             :  *
     551             :  * @note This method has only an effect on the in-memory feature object. If
     552             :  * this object comes from a layer and the modifications must be serialized back
     553             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
     554             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
     555             :  *
     556             :  * @param hFeat handle to the feature on which new geometry is applied to.
     557             :  * @param hGeom handle to the new geometry to apply to feature.
     558             :  *
     559             :  * @return OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if
     560             :  * the geometry type is illegal for the OGRFeatureDefn (checking not yet
     561             :  * implemented).
     562             :  */
     563             : 
     564      236227 : OGRErr OGR_F_SetGeometry(OGRFeatureH hFeat, OGRGeometryH hGeom)
     565             : 
     566             : {
     567      236227 :     VALIDATE_POINTER1(hFeat, "OGR_F_SetGeometry", OGRERR_FAILURE);
     568             : 
     569      472454 :     return OGRFeature::FromHandle(hFeat)->SetGeometry(
     570      472454 :         OGRGeometry::FromHandle(hGeom));
     571             : }
     572             : 
     573             : /************************************************************************/
     574             : /*                        SetGeometry()                                 */
     575             : /************************************************************************/
     576             : 
     577             : /**
     578             :  * \brief Set feature geometry.
     579             :  *
     580             :  * This method is the same as the C function OGR_F_SetGeometryDirectly().
     581             :  *
     582             :  * @note This method has only an effect on the in-memory feature object. If
     583             :  * this object comes from a layer and the modifications must be serialized back
     584             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
     585             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
     586             :  *
     587             :  * @param poGeomIn new geometry to apply to feature. Passing NULL value here
     588             :  * is correct and it will result in deallocation of currently assigned geometry
     589             :  * without assigning new one.
     590             :  *
     591             :  * @return OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if
     592             :  * the geometry type is illegal for the OGRFeatureDefn (checking not yet
     593             :  * implemented).
     594             :  *
     595             :  * @since GDAL 3.11
     596             :  */
     597             : 
     598       11153 : OGRErr OGRFeature::SetGeometry(std::unique_ptr<OGRGeometry> poGeomIn)
     599             : 
     600             : {
     601       11153 :     return SetGeomField(0, std::move(poGeomIn));
     602             : }
     603             : 
     604             : /************************************************************************/
     605             : /*                           StealGeometry()                            */
     606             : /************************************************************************/
     607             : 
     608             : /**
     609             :  * \brief Take away ownership of geometry.
     610             :  *
     611             :  * Fetch the geometry from this feature, and clear the reference to the
     612             :  * geometry on the feature.  This is a mechanism for the application to
     613             :  * take over ownership of the geometry from the feature without copying.
     614             :  * Sort of an inverse to SetGeometryDirectly().
     615             :  *
     616             :  * After this call the OGRFeature will have a NULL geometry.
     617             :  *
     618             :  * @return the pointer to the geometry.
     619             :  */
     620             : 
     621        2575 : OGRGeometry *OGRFeature::StealGeometry()
     622             : 
     623             : {
     624        2575 :     if (GetGeomFieldCount() > 0)
     625             :     {
     626        2563 :         OGRGeometry *poReturn = papoGeometries[0];
     627        2563 :         papoGeometries[0] = nullptr;
     628        2563 :         return poReturn;
     629             :     }
     630             : 
     631          12 :     return nullptr;
     632             : }
     633             : 
     634             : /**
     635             :  * \brief Take away ownership of geometry.
     636             :  *
     637             :  * Fetch the geometry from this feature, and clear the reference to the
     638             :  * geometry on the feature.  This is a mechanism for the application to
     639             :  * take over ownership of the geometry from the feature without copying.
     640             :  * Sort of an inverse to SetGeometryDirectly().
     641             :  *
     642             :  * After this call the OGRFeature will have a NULL geometry.
     643             :  *
     644             :  * @param iGeomField index of the geometry field.
     645             :  *
     646             :  * @return the pointer to the geometry.
     647             :  */
     648             : 
     649        9949 : OGRGeometry *OGRFeature::StealGeometry(int iGeomField)
     650             : 
     651             : {
     652        9949 :     if (iGeomField >= 0 && iGeomField < GetGeomFieldCount())
     653             :     {
     654        9948 :         OGRGeometry *poReturn = papoGeometries[iGeomField];
     655        9948 :         papoGeometries[iGeomField] = nullptr;
     656        9948 :         return poReturn;
     657             :     }
     658             : 
     659           1 :     return nullptr;
     660             : }
     661             : 
     662             : /************************************************************************/
     663             : /*                        OGR_F_StealGeometry()                         */
     664             : /************************************************************************/
     665             : 
     666             : /**
     667             :  * \brief Take away ownership of geometry.
     668             :  *
     669             :  * Fetch the geometry from this feature, and clear the reference to the
     670             :  * geometry on the feature.  This is a mechanism for the application to
     671             :  * take over ownership of the geometry from the feature without copying.
     672             :  * Sort of an inverse to OGR_FSetGeometryDirectly().
     673             :  *
     674             :  * After this call the OGRFeature will have a NULL geometry.
     675             :  *
     676             :  * @param hFeat feature from which to steal the first geometry.
     677             :  * @return the pointer to the stolen geometry.
     678             :  */
     679             : 
     680        1979 : OGRGeometryH OGR_F_StealGeometry(OGRFeatureH hFeat)
     681             : 
     682             : {
     683        1979 :     VALIDATE_POINTER1(hFeat, "OGR_F_StealGeometry", nullptr);
     684             : 
     685        1979 :     return OGRGeometry::ToHandle(
     686        1979 :         OGRFeature::FromHandle(hFeat)->StealGeometry());
     687             : }
     688             : 
     689             : /************************************************************************/
     690             : /*                       OGR_F_StealGeometryEx()                        */
     691             : /************************************************************************/
     692             : 
     693             : /**
     694             :  * \brief Take away ownership of geometry.
     695             :  *
     696             :  * Fetch the geometry from this feature, and clear the reference to the
     697             :  * geometry on the feature.  This is a mechanism for the application to
     698             :  * take over ownership of the geometry from the feature without copying.
     699             :  * This is the functional opposite of OGR_F_SetGeomFieldDirectly.
     700             :  *
     701             :  * After this call the OGRFeature will have a NULL geometry for the
     702             :  * geometry field of index iGeomField.
     703             :  *
     704             :  * @param hFeat feature from which to steal a geometry.
     705             :  * @param iGeomField index of the geometry field to steal.
     706             :  * @return the pointer to the stolen geometry.
     707             :  * @since GDAL 3.5
     708             :  */
     709             : 
     710           1 : OGRGeometryH OGR_F_StealGeometryEx(OGRFeatureH hFeat, int iGeomField)
     711             : 
     712             : {
     713           1 :     VALIDATE_POINTER1(hFeat, "OGR_F_StealGeometryEx", nullptr);
     714             : 
     715           1 :     return OGRGeometry::ToHandle(
     716           1 :         OGRFeature::FromHandle(hFeat)->StealGeometry(iGeomField));
     717             : }
     718             : 
     719             : /************************************************************************/
     720             : /*                           GetGeometryRef()                           */
     721             : /************************************************************************/
     722             : 
     723             : /**
     724             :  * \fn OGRGeometry *OGRFeature::GetGeometryRef();
     725             :  *
     726             :  * \brief Fetch pointer to feature geometry.
     727             :  *
     728             :  * This method is essentially the same as the C function OGR_F_GetGeometryRef().
     729             :  * (the only difference is that the C function honours
     730             :  * OGRGetNonLinearGeometriesEnabledFlag())
     731             :  *
     732             :  * This is equivalent to calling OGRFeature::GetGeomFieldRef(0).
     733             :  *
     734             :  * @return pointer to internal feature geometry.  This object should
     735             :  * not be modified.
     736             :  */
     737     2340710 : OGRGeometry *OGRFeature::GetGeometryRef()
     738             : 
     739             : {
     740     2340710 :     if (GetGeomFieldCount() > 0)
     741     2329740 :         return GetGeomFieldRef(0);
     742             : 
     743       10971 :     return nullptr;
     744             : }
     745             : 
     746             : /**
     747             :  * \fn const OGRGeometry *OGRFeature::GetGeometryRef() const;
     748             :  *
     749             :  * \brief Fetch pointer to feature geometry.
     750             :  *
     751             :  * This method is essentially the same as the C function OGR_F_GetGeometryRef().
     752             :  * (the only difference is that the C function honours
     753             :  * OGRGetNonLinearGeometriesEnabledFlag())
     754             :  *
     755             :  * @return pointer to internal feature geometry.  This object should
     756             :  * not be modified.
     757             :  */
     758      267703 : const OGRGeometry *OGRFeature::GetGeometryRef() const
     759             : 
     760             : {
     761      267703 :     if (GetGeomFieldCount() > 0)
     762      263917 :         return GetGeomFieldRef(0);
     763             : 
     764        3786 :     return nullptr;
     765             : }
     766             : 
     767             : /************************************************************************/
     768             : /*                        OGR_F_GetGeometryRef()                        */
     769             : /************************************************************************/
     770             : 
     771             : /**
     772             :  * \brief Fetch a handle to feature geometry.
     773             :  *
     774             :  * This function is essentially the same as the C++ method
     775             :  * OGRFeature::GetGeometryRef() (the only difference is that this C function
     776             :  * honours OGRGetNonLinearGeometriesEnabledFlag())
     777             :  *
     778             :  * @param hFeat handle to the feature to get geometry from.
     779             :  * @return a handle to internal feature geometry.  This object should
     780             :  * not be modified.
     781             :  */
     782             : 
     783       38938 : OGRGeometryH OGR_F_GetGeometryRef(OGRFeatureH hFeat)
     784             : 
     785             : {
     786       38938 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetGeometryRef", nullptr);
     787             : 
     788       38938 :     OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
     789       38938 :     OGRGeometry *poGeom = poFeature->GetGeometryRef();
     790             : 
     791       38939 :     if (!OGRGetNonLinearGeometriesEnabledFlag() && poGeom != nullptr &&
     792           1 :         OGR_GT_IsNonLinear(poGeom->getGeometryType()))
     793             :     {
     794             :         const OGRwkbGeometryType eTargetType =
     795           1 :             OGR_GT_GetLinear(poGeom->getGeometryType());
     796           1 :         poGeom = OGRGeometryFactory::forceTo(poFeature->StealGeometry(),
     797             :                                              eTargetType);
     798           1 :         poFeature->SetGeomFieldDirectly(0, poGeom);
     799           1 :         poGeom = poFeature->GetGeometryRef();
     800             :     }
     801             : 
     802       38938 :     return OGRGeometry::ToHandle(poGeom);
     803             : }
     804             : 
     805             : /************************************************************************/
     806             : /*                           GetGeomFieldRef()                          */
     807             : /************************************************************************/
     808             : 
     809             : /**
     810             :  * \brief Fetch pointer to feature geometry.
     811             :  *
     812             :  * This method is the same as the C function OGR_F_GetGeomFieldRef().
     813             :  *
     814             :  * @param iField geometry field to get.
     815             :  *
     816             :  * @return pointer to internal feature geometry.  This object should
     817             :  * not be modified.
     818             :  *
     819             :  */
     820     3779100 : OGRGeometry *OGRFeature::GetGeomFieldRef(int iField)
     821             : 
     822             : {
     823     3779100 :     if (iField < 0 || iField >= GetGeomFieldCount())
     824           8 :         return nullptr;
     825             :     else
     826     3779090 :         return papoGeometries[iField];
     827             : }
     828             : 
     829             : /**
     830             :  * \brief Fetch pointer to feature geometry.
     831             :  *
     832             :  * This method is the same as the C function OGR_F_GetGeomFieldRef().
     833             :  *
     834             :  * @param iField geometry field to get.
     835             :  *
     836             :  * @return pointer to internal feature geometry.  This object should
     837             :  * not be modified.
     838             :  */
     839      288012 : const OGRGeometry *OGRFeature::GetGeomFieldRef(int iField) const
     840             : 
     841             : {
     842      288012 :     if (iField < 0 || iField >= GetGeomFieldCount())
     843          23 :         return nullptr;
     844             :     else
     845      287989 :         return papoGeometries[iField];
     846             : }
     847             : 
     848             : /************************************************************************/
     849             : /*                           GetGeomFieldRef()                          */
     850             : /************************************************************************/
     851             : 
     852             : /**
     853             :  * \brief Fetch pointer to feature geometry.
     854             :  *
     855             :  * @param pszFName name of geometry field to get.
     856             :  *
     857             :  * @return pointer to internal feature geometry.  This object should
     858             :  * not be modified.
     859             :  *
     860             :  */
     861           0 : OGRGeometry *OGRFeature::GetGeomFieldRef(const char *pszFName)
     862             : 
     863             : {
     864           0 :     const int iField = GetGeomFieldIndex(pszFName);
     865           0 :     if (iField < 0)
     866           0 :         return nullptr;
     867             : 
     868           0 :     return papoGeometries[iField];
     869             : }
     870             : 
     871             : /**
     872             :  * \brief Fetch pointer to feature geometry.
     873             :  *
     874             :  * @param pszFName name of geometry field to get.
     875             :  *
     876             :  * @return pointer to internal feature geometry.  This object should
     877             :  * not be modified.
     878             :  */
     879           0 : const OGRGeometry *OGRFeature::GetGeomFieldRef(const char *pszFName) const
     880             : 
     881             : {
     882           0 :     const int iField = GetGeomFieldIndex(pszFName);
     883           0 :     if (iField < 0)
     884           0 :         return nullptr;
     885             : 
     886           0 :     return papoGeometries[iField];
     887             : }
     888             : 
     889             : /************************************************************************/
     890             : /*                       OGR_F_GetGeomFieldRef()                        */
     891             : /************************************************************************/
     892             : 
     893             : /**
     894             :  * \brief Fetch a handle to feature geometry.
     895             :  *
     896             :  * This function is the same as the C++ method OGRFeature::GetGeomFieldRef().
     897             :  *
     898             :  * @param hFeat handle to the feature to get geometry from.
     899             :  * @param iField geometry field to get.
     900             :  * @return a handle to internal feature geometry.  This object should
     901             :  * not be modified.
     902             :  *
     903             :  */
     904             : 
     905         388 : OGRGeometryH OGR_F_GetGeomFieldRef(OGRFeatureH hFeat, int iField)
     906             : 
     907             : {
     908         388 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetGeomFieldRef", nullptr);
     909             : 
     910         388 :     OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
     911         388 :     OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iField);
     912             : 
     913         389 :     if (!OGRGetNonLinearGeometriesEnabledFlag() && poGeom != nullptr &&
     914           1 :         OGR_GT_IsNonLinear(poGeom->getGeometryType()))
     915             :     {
     916             :         const OGRwkbGeometryType eTargetType =
     917           1 :             OGR_GT_GetLinear(poGeom->getGeometryType());
     918           1 :         poGeom = OGRGeometryFactory::forceTo(poFeature->StealGeometry(iField),
     919             :                                              eTargetType);
     920           1 :         poFeature->SetGeomFieldDirectly(iField, poGeom);
     921           1 :         poGeom = poFeature->GetGeomFieldRef(iField);
     922             :     }
     923             : 
     924         388 :     return OGRGeometry::ToHandle(poGeom);
     925             : }
     926             : 
     927             : /************************************************************************/
     928             : /*                       SetGeomFieldDirectly()                         */
     929             : /************************************************************************/
     930             : 
     931             : /**
     932             :  * \brief Set feature geometry of a specified geometry field.
     933             :  *
     934             :  * This method updates the features geometry, and operates the same as
     935             :  * SetGeomField(), except that this method assumes ownership of the
     936             :  * passed geometry (even in case of failure of that function).
     937             :  *
     938             :  * This method is the same as the C function OGR_F_SetGeomFieldDirectly().
     939             :  *
     940             :  * @param iField geometry field to set.
     941             :  * @param poGeomIn new geometry to apply to feature. Passing NULL value here
     942             :  * is correct and it will result in deallocation of currently assigned geometry
     943             :  * without assigning new one.
     944             :  *
     945             :  * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is invalid,
     946             :  * or OGRERR_UNSUPPORTED_GEOMETRY_TYPE if the geometry type is illegal for the
     947             :  * OGRFeatureDefn (checking not yet implemented).
     948             :  *
     949             :  */
     950             : 
     951       42620 : OGRErr OGRFeature::SetGeomFieldDirectly(int iField, OGRGeometry *poGeomIn)
     952             : {
     953       42620 :     if (poGeomIn && poGeomIn == GetGeomFieldRef(iField))
     954             :     {
     955           0 :         return OGRERR_NONE;
     956             :     }
     957             : 
     958       42620 :     return SetGeomField(iField, std::unique_ptr<OGRGeometry>(poGeomIn));
     959             : }
     960             : 
     961             : /************************************************************************/
     962             : /*                     OGR_F_SetGeomFieldDirectly()                     */
     963             : /************************************************************************/
     964             : 
     965             : /**
     966             :  * \brief Set feature geometry of a specified geometry field.
     967             :  *
     968             :  * This function updates the features geometry, and operates the same as
     969             :  * SetGeomField(), except that this function assumes ownership of the
     970             :  * passed geometry (even in case of failure of that function).
     971             :  *
     972             :  * This function is the same as the C++ method
     973             :  * OGRFeature::SetGeomFieldDirectly.
     974             :  *
     975             :  * @param hFeat handle to the feature on which to apply the geometry.
     976             :  * @param iField geometry field to set.
     977             :  * @param hGeom handle to the new geometry to apply to feature.
     978             :  *
     979             :  * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is invalid,
     980             :  * or OGR_UNSUPPORTED_GEOMETRY_TYPE if the geometry type is illegal for the
     981             :  * OGRFeatureDefn (checking not yet implemented).
     982             :  *
     983             :  */
     984             : 
     985          34 : OGRErr OGR_F_SetGeomFieldDirectly(OGRFeatureH hFeat, int iField,
     986             :                                   OGRGeometryH hGeom)
     987             : 
     988             : {
     989          34 :     VALIDATE_POINTER1(hFeat, "OGR_F_SetGeomFieldDirectly", OGRERR_FAILURE);
     990             : 
     991          34 :     return OGRFeature::FromHandle(hFeat)->SetGeomFieldDirectly(
     992          34 :         iField, OGRGeometry::FromHandle(hGeom));
     993             : }
     994             : 
     995             : /************************************************************************/
     996             : /*                            SetGeomField()                            */
     997             : /************************************************************************/
     998             : 
     999             : /**
    1000             :  * \brief Set feature geometry of a specified geometry field.
    1001             :  *
    1002             :  * This method updates the features geometry, and operates the same as
    1003             :  * SetGeomFieldDirectly(), except that this method does not assume ownership
    1004             :  * of the passed geometry, but instead makes a copy of it.
    1005             :  *
    1006             :  * This method is the same as the C function OGR_F_SetGeomField().
    1007             :  *
    1008             :  * @param iField geometry field to set.
    1009             :  * @param poGeomIn new geometry to apply to feature. Passing NULL value here
    1010             :  * is correct and it will result in deallocation of currently assigned geometry
    1011             :  * without assigning new one.
    1012             :  *
    1013             :  * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is invalid,
    1014             :  * or OGR_UNSUPPORTED_GEOMETRY_TYPE if the geometry type is illegal for the
    1015             :  * OGRFeatureDefn (checking not yet implemented).
    1016             :  *
    1017             :  */
    1018             : 
    1019      247578 : OGRErr OGRFeature::SetGeomField(int iField, const OGRGeometry *poGeomIn)
    1020             : 
    1021             : {
    1022      247578 :     if (iField < 0 || iField >= GetGeomFieldCount())
    1023           1 :         return OGRERR_FAILURE;
    1024             : 
    1025      247577 :     if (papoGeometries[iField] != poGeomIn)
    1026             :     {
    1027      246617 :         delete papoGeometries[iField];
    1028             : 
    1029      246617 :         if (poGeomIn != nullptr)
    1030      246506 :             papoGeometries[iField] = poGeomIn->clone();
    1031             :         else
    1032         111 :             papoGeometries[iField] = nullptr;
    1033             :     }
    1034             : 
    1035             :     // TODO(schwehr): Verify that the geometry matches the defn's type.
    1036             : 
    1037      247577 :     return OGRERR_NONE;
    1038             : }
    1039             : 
    1040             : /************************************************************************/
    1041             : /*                        OGR_F_SetGeomField()                          */
    1042             : /************************************************************************/
    1043             : 
    1044             : /**
    1045             :  * \brief Set feature geometry of a specified geometry field.
    1046             :  *
    1047             :  * This function updates the features geometry, and operates the same as
    1048             :  * SetGeometryDirectly(), except that this function does not assume ownership
    1049             :  * of the passed geometry, but instead makes a copy of it.
    1050             :  *
    1051             :  * This function is the same as the C++ OGRFeature::SetGeomField().
    1052             :  *
    1053             :  * @param hFeat handle to the feature on which new geometry is applied to.
    1054             :  * @param iField geometry field to set.
    1055             :  * @param hGeom handle to the new geometry to apply to feature.
    1056             :  *
    1057             :  * @return OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if
    1058             :  * the geometry type is illegal for the OGRFeatureDefn (checking not yet
    1059             :  * implemented).
    1060             :  */
    1061             : 
    1062         257 : OGRErr OGR_F_SetGeomField(OGRFeatureH hFeat, int iField, OGRGeometryH hGeom)
    1063             : 
    1064             : {
    1065         257 :     VALIDATE_POINTER1(hFeat, "OGR_F_SetGeomField", OGRERR_FAILURE);
    1066             : 
    1067         514 :     return OGRFeature::FromHandle(hFeat)->SetGeomField(
    1068         514 :         iField, OGRGeometry::FromHandle(hGeom));
    1069             : }
    1070             : 
    1071             : /************************************************************************/
    1072             : /*                       SetGeomField()                                 */
    1073             : /************************************************************************/
    1074             : 
    1075             : /**
    1076             :  * \brief Set feature geometry of a specified geometry field.
    1077             :  *
    1078             :  * This method is the same as the C function OGR_F_SetGeomFieldDirectly().
    1079             :  *
    1080             :  * @param iField geometry field to set.
    1081             :  * @param poGeomIn new geometry to apply to feature. Passing NULL value here
    1082             :  * is correct and it will result in deallocation of currently assigned geometry
    1083             :  * without assigning new one.
    1084             :  *
    1085             :  * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is invalid,
    1086             :  * or OGRERR_UNSUPPORTED_GEOMETRY_TYPE if the geometry type is illegal for the
    1087             :  * OGRFeatureDefn (checking not yet implemented).
    1088             :  *
    1089             :  * @since GDAL 3.11
    1090             :  */
    1091             : 
    1092     1173940 : OGRErr OGRFeature::SetGeomField(int iField,
    1093             :                                 std::unique_ptr<OGRGeometry> poGeomIn)
    1094             : 
    1095             : {
    1096     1173940 :     if (iField < 0 || iField >= GetGeomFieldCount())
    1097             :     {
    1098        5444 :         return OGRERR_FAILURE;
    1099             :     }
    1100             : 
    1101     1168500 :     if (papoGeometries[iField] != poGeomIn.get())
    1102             :     {
    1103     1168250 :         delete papoGeometries[iField];
    1104     1168250 :         papoGeometries[iField] = poGeomIn.release();
    1105             :     }
    1106             : 
    1107     1168500 :     return OGRERR_NONE;
    1108             : }
    1109             : 
    1110             : /************************************************************************/
    1111             : /*                               Clone()                                */
    1112             : /************************************************************************/
    1113             : 
    1114             : /**
    1115             :  * \brief Duplicate feature.
    1116             :  *
    1117             :  * The newly created feature is owned by the caller, and will have its own
    1118             :  * reference to the OGRFeatureDefn.
    1119             :  *
    1120             :  * This method is the same as the C function OGR_F_Clone().
    1121             :  *
    1122             :  * @return new feature, exactly matching this feature. Or, starting with GDAL
    1123             :  * 2.1, NULL in case of out of memory situation.
    1124             :  */
    1125             : 
    1126      664101 : OGRFeature *OGRFeature::Clone() const
    1127             : 
    1128             : {
    1129      664101 :     OGRFeature *poNew = CreateFeature(poDefn);
    1130      664101 :     if (poNew == nullptr)
    1131           0 :         return nullptr;
    1132             : 
    1133      664101 :     if (!CopySelfTo(poNew))
    1134             :     {
    1135           0 :         delete poNew;
    1136           0 :         return nullptr;
    1137             :     }
    1138             : 
    1139      664101 :     return poNew;
    1140             : }
    1141             : 
    1142             : /************************************************************************/
    1143             : /*                            OGR_F_Clone()                             */
    1144             : /************************************************************************/
    1145             : 
    1146             : /**
    1147             :  * \brief Duplicate feature.
    1148             :  *
    1149             :  * The newly created feature is owned by the caller, and will have its own
    1150             :  * reference to the OGRFeatureDefn.
    1151             :  *
    1152             :  * This function is the same as the C++ method OGRFeature::Clone().
    1153             :  *
    1154             :  * @param hFeat handle to the feature to clone.
    1155             :  * @return a handle to the new feature, exactly matching this feature.
    1156             :  */
    1157             : 
    1158          49 : OGRFeatureH OGR_F_Clone(OGRFeatureH hFeat)
    1159             : 
    1160             : {
    1161          49 :     VALIDATE_POINTER1(hFeat, "OGR_F_Clone", nullptr);
    1162             : 
    1163          49 :     return OGRFeature::ToHandle(OGRFeature::FromHandle(hFeat)->Clone());
    1164             : }
    1165             : 
    1166             : /************************************************************************/
    1167             : /*                             CopySelfTo()                             */
    1168             : /************************************************************************/
    1169             : 
    1170             : /**
    1171             :  * \brief Copies the innards of this OGRFeature into the supplied object.
    1172             :  *
    1173             :  * This is mainly intended to allow derived classes to implement their own
    1174             :  * Clone functions.
    1175             :  *
    1176             :  * @param poNew The object into which to copy the data of this object.
    1177             :  * @return True if successful, false if the copy failed.
    1178             :  */
    1179             : 
    1180      667797 : bool OGRFeature::CopySelfTo(OGRFeature *poNew) const
    1181             : {
    1182      667797 :     const int nFieldCount = poDefn->GetFieldCountUnsafe();
    1183     4897610 :     for (int i = 0; i < nFieldCount; i++)
    1184             :     {
    1185     4229810 :         if (!poNew->SetFieldInternal(i, pauFields + i))
    1186             :         {
    1187           0 :             return false;
    1188             :         }
    1189             :     }
    1190      667797 :     if (poNew->papoGeometries)
    1191             :     {
    1192     1031420 :         for (int i = 0; i < poDefn->GetGeomFieldCount(); i++)
    1193             :         {
    1194      363627 :             if (papoGeometries[i] != nullptr)
    1195             :             {
    1196      360315 :                 poNew->papoGeometries[i] = papoGeometries[i]->clone();
    1197      360315 :                 if (poNew->papoGeometries[i] == nullptr)
    1198             :                 {
    1199           0 :                     return false;
    1200             :                 }
    1201             :             }
    1202             :         }
    1203             :     }
    1204             : 
    1205      667797 :     if (m_pszStyleString != nullptr)
    1206             :     {
    1207      325918 :         poNew->m_pszStyleString = VSI_STRDUP_VERBOSE(m_pszStyleString);
    1208      325918 :         if (poNew->m_pszStyleString == nullptr)
    1209             :         {
    1210           0 :             return false;
    1211             :         }
    1212             :     }
    1213             : 
    1214      667797 :     poNew->SetFID(GetFID());
    1215             : 
    1216      667797 :     if (m_pszNativeData != nullptr)
    1217             :     {
    1218         158 :         poNew->m_pszNativeData = VSI_STRDUP_VERBOSE(m_pszNativeData);
    1219         158 :         if (poNew->m_pszNativeData == nullptr)
    1220             :         {
    1221           0 :             return false;
    1222             :         }
    1223             :     }
    1224             : 
    1225      667797 :     if (m_pszNativeMediaType != nullptr)
    1226             :     {
    1227         158 :         poNew->m_pszNativeMediaType = VSI_STRDUP_VERBOSE(m_pszNativeMediaType);
    1228         158 :         if (poNew->m_pszNativeMediaType == nullptr)
    1229             :         {
    1230           0 :             return false;
    1231             :         }
    1232             :     }
    1233             : 
    1234      667797 :     return true;
    1235             : }
    1236             : 
    1237             : /************************************************************************/
    1238             : /*                           GetFieldCount()                            */
    1239             : /************************************************************************/
    1240             : 
    1241             : /**
    1242             :  * \fn int OGRFeature::GetFieldCount() const;
    1243             :  *
    1244             :  * \brief Fetch number of fields on this feature.
    1245             :  * This will always be the same
    1246             :  * as the field count for the OGRFeatureDefn.
    1247             :  *
    1248             :  * This method is the same as the C function OGR_F_GetFieldCount().
    1249             :  *
    1250             :  * @return count of fields.
    1251             :  */
    1252             : 
    1253             : /************************************************************************/
    1254             : /*                        OGR_F_GetFieldCount()                         */
    1255             : /************************************************************************/
    1256             : 
    1257             : /**
    1258             :  * \brief Fetch number of fields on this feature
    1259             :  * This will always be the same
    1260             :  * as the field count for the OGRFeatureDefn.
    1261             :  *
    1262             :  * This function is the same as the C++ method OGRFeature::GetFieldCount().
    1263             :  *
    1264             :  * @param hFeat handle to the feature to get the fields count from.
    1265             :  * @return count of fields.
    1266             :  */
    1267             : 
    1268      111311 : int OGR_F_GetFieldCount(OGRFeatureH hFeat)
    1269             : 
    1270             : {
    1271      111311 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldCount", 0);
    1272             : 
    1273      111311 :     return OGRFeature::FromHandle(hFeat)->GetFieldCount();
    1274             : }
    1275             : 
    1276             : /************************************************************************/
    1277             : /*                          GetFieldDefnRef()                           */
    1278             : /************************************************************************/
    1279             : 
    1280             : /**
    1281             :  * \fn const OGRFieldDefn *OGRFeature::GetFieldDefnRef( int iField ) const;
    1282             :  *
    1283             :  * \brief Fetch definition for this field.
    1284             :  *
    1285             :  * This method is the same as the C function OGR_F_GetFieldDefnRef().
    1286             :  *
    1287             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    1288             :  *
    1289             :  * @return the field definition (from the OGRFeatureDefn).  This is an
    1290             :  * internal reference, and should not be deleted or modified.
    1291             :  */
    1292             : 
    1293             : /************************************************************************/
    1294             : /*                       OGR_F_GetFieldDefnRef()                        */
    1295             : /************************************************************************/
    1296             : 
    1297             : /**
    1298             :  * \brief Fetch definition for this field.
    1299             :  *
    1300             :  * This function is the same as the C++ method OGRFeature::GetFieldDefnRef().
    1301             :  *
    1302             :  * @param hFeat handle to the feature on which the field is found.
    1303             :  * @param i the field to fetch, from 0 to GetFieldCount()-1.
    1304             :  *
    1305             :  * @return a handle to the field definition (from the OGRFeatureDefn).
    1306             :  * This is an internal reference, and should not be deleted or modified.
    1307             :  */
    1308             : 
    1309      188943 : OGRFieldDefnH OGR_F_GetFieldDefnRef(OGRFeatureH hFeat, int i)
    1310             : 
    1311             : {
    1312      188943 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldDefnRef", nullptr);
    1313             : 
    1314      188943 :     OGRFeature *poFeat = OGRFeature::FromHandle(hFeat);
    1315             : 
    1316      188943 :     return OGRFieldDefn::ToHandle(
    1317      188943 :         const_cast<OGRFieldDefn *>(poFeat->GetFieldDefnRef(i)));
    1318             : }
    1319             : 
    1320             : /************************************************************************/
    1321             : /*                           GetFieldIndex()                            */
    1322             : /************************************************************************/
    1323             : 
    1324             : /**
    1325             :  * \fn int OGRFeature::GetFieldIndex( const char * pszName ) const;
    1326             :  *
    1327             :  * \brief Fetch the field index given field name.
    1328             :  *
    1329             :  * This is a cover for the OGRFeatureDefn::GetFieldIndex() method.
    1330             :  *
    1331             :  * This method is the same as the C function OGR_F_GetFieldIndex().
    1332             :  *
    1333             :  * @param pszName the name of the field to search for.
    1334             :  *
    1335             :  * @return the field index, or -1 if no matching field is found.
    1336             :  */
    1337             : 
    1338             : /************************************************************************/
    1339             : /*                        OGR_F_GetFieldIndex()                         */
    1340             : /************************************************************************/
    1341             : 
    1342             : /**
    1343             :  * \brief Fetch the field index given field name.
    1344             :  *
    1345             :  * This is a cover for the OGRFeatureDefn::GetFieldIndex() method.
    1346             :  *
    1347             :  * This function is the same as the C++ method OGRFeature::GetFieldIndex().
    1348             :  *
    1349             :  * @param hFeat handle to the feature on which the field is found.
    1350             :  * @param pszName the name of the field to search for.
    1351             :  *
    1352             :  * @return the field index, or -1 if no matching field is found.
    1353             :  */
    1354             : 
    1355        3456 : int OGR_F_GetFieldIndex(OGRFeatureH hFeat, const char *pszName)
    1356             : 
    1357             : {
    1358        3456 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldIndex", 0);
    1359             : 
    1360        3456 :     return OGRFeature::FromHandle(hFeat)->GetFieldIndex(pszName);
    1361             : }
    1362             : 
    1363             : /************************************************************************/
    1364             : /*                         GetGeomFieldCount()                          */
    1365             : /************************************************************************/
    1366             : 
    1367             : /**
    1368             :  * \fn int OGRFeature::GetGeomFieldCount() const;
    1369             :  *
    1370             :  * \brief Fetch number of geometry fields on this feature.
    1371             :  * This will always be the same
    1372             :  * as the geometry field count for the OGRFeatureDefn.
    1373             :  *
    1374             :  * This method is the same as the C function OGR_F_GetGeomFieldCount().
    1375             :  *
    1376             :  * @return count of geometry fields.
    1377             :  *
    1378             :  */
    1379             : 
    1380             : /************************************************************************/
    1381             : /*                      OGR_F_GetGeomFieldCount()                       */
    1382             : /************************************************************************/
    1383             : 
    1384             : /**
    1385             :  * \brief Fetch number of geometry fields on this feature
    1386             :  * This will always be the same
    1387             :  * as the geometry field count for the OGRFeatureDefn.
    1388             :  *
    1389             :  * This function is the same as the C++ method OGRFeature::GetGeomFieldCount().
    1390             :  *
    1391             :  * @param hFeat handle to the feature to get the geometry fields count from.
    1392             :  * @return count of geometry fields.
    1393             :  *
    1394             :  */
    1395             : 
    1396         121 : int OGR_F_GetGeomFieldCount(OGRFeatureH hFeat)
    1397             : 
    1398             : {
    1399         121 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetGeomFieldCount", 0);
    1400             : 
    1401         121 :     return OGRFeature::FromHandle(hFeat)->GetGeomFieldCount();
    1402             : }
    1403             : 
    1404             : /************************************************************************/
    1405             : /*                        GetGeomFieldDefnRef()                         */
    1406             : /************************************************************************/
    1407             : 
    1408             : /* clang-format off */
    1409             : /**
    1410             :  * \fn const OGRGeomFieldDefn *OGRFeature::GetGeomFieldDefnRef( int iGeomField ) const;
    1411             :  *
    1412             :  * \brief Fetch definition for this geometry field.
    1413             :  *
    1414             :  * This method is the same as the C function OGR_F_GetGeomFieldDefnRef().
    1415             :  *
    1416             :  * @param iGeomField the field to fetch, from 0 to GetGeomFieldCount()-1.
    1417             :  *
    1418             :  * @return the field definition (from the OGRFeatureDefn).  This is an
    1419             :  * internal reference, and should not be deleted or modified.
    1420             :  *
    1421             :  */
    1422             : /* clang-format on */
    1423             : 
    1424             : /************************************************************************/
    1425             : /*                       OGR_F_GetGeomFieldDefnRef()                    */
    1426             : /************************************************************************/
    1427             : 
    1428             : /**
    1429             :  * \brief Fetch definition for this geometry field.
    1430             :  *
    1431             :  * This function is the same as the C++ method
    1432             :  * OGRFeature::GetGeomFieldDefnRef().
    1433             :  *
    1434             :  * @param hFeat handle to the feature on which the field is found.
    1435             :  * @param i the field to fetch, from 0 to GetGeomFieldCount()-1.
    1436             :  *
    1437             :  * @return a handle to the field definition (from the OGRFeatureDefn).
    1438             :  * This is an internal reference, and should not be deleted or modified.
    1439             :  *
    1440             :  */
    1441             : 
    1442           2 : OGRGeomFieldDefnH OGR_F_GetGeomFieldDefnRef(OGRFeatureH hFeat, int i)
    1443             : 
    1444             : {
    1445           2 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetGeomFieldDefnRef", nullptr);
    1446             : 
    1447           2 :     return OGRGeomFieldDefn::ToHandle(const_cast<OGRGeomFieldDefn *>(
    1448           2 :         OGRFeature::FromHandle(hFeat)->GetGeomFieldDefnRef(i)));
    1449             : }
    1450             : 
    1451             : /************************************************************************/
    1452             : /*                           GetGeomFieldIndex()                            */
    1453             : /************************************************************************/
    1454             : 
    1455             : /**
    1456             :  * \fn int OGRFeature::GetGeomFieldIndex( const char * pszName );
    1457             :  *
    1458             :  * \brief Fetch the geometry field index given geometry field name.
    1459             :  *
    1460             :  * This is a cover for the OGRFeatureDefn::GetGeomFieldIndex() method.
    1461             :  *
    1462             :  * This method is the same as the C function OGR_F_GetGeomFieldIndex().
    1463             :  *
    1464             :  * @param pszName the name of the geometry field to search for.
    1465             :  *
    1466             :  * @return the geometry field index, or -1 if no matching geometry field is
    1467             :  * found.
    1468             :  *
    1469             :  */
    1470             : 
    1471             : /************************************************************************/
    1472             : /*                       OGR_F_GetGeomFieldIndex()                      */
    1473             : /************************************************************************/
    1474             : 
    1475             : /**
    1476             :  * \brief Fetch the geometry field index given geometry field name.
    1477             :  *
    1478             :  * This is a cover for the OGRFeatureDefn::GetGeomFieldIndex() method.
    1479             :  *
    1480             :  * This function is the same as the C++ method OGRFeature::GetGeomFieldIndex().
    1481             :  *
    1482             :  * @param hFeat handle to the feature on which the geometry field is found.
    1483             :  * @param pszName the name of the geometry field to search for.
    1484             :  *
    1485             :  * @return the geometry field index, or -1 if no matching geometry field is
    1486             :  * found.
    1487             :  *
    1488             :  */
    1489             : 
    1490         146 : int OGR_F_GetGeomFieldIndex(OGRFeatureH hFeat, const char *pszName)
    1491             : 
    1492             : {
    1493         146 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetGeomFieldIndex", 0);
    1494             : 
    1495         146 :     return OGRFeature::FromHandle(hFeat)->GetGeomFieldIndex(pszName);
    1496             : }
    1497             : 
    1498             : /************************************************************************/
    1499             : /*                             IsFieldSet()                             */
    1500             : /************************************************************************/
    1501             : 
    1502             : /**
    1503             :  * \brief Test if a field has ever been assigned a value or not.
    1504             :  *
    1505             :  * This method is the same as the C function OGR_F_IsFieldSet().
    1506             :  *
    1507             :  * @param iField the field to test.
    1508             :  *
    1509             :  * @return TRUE if the field has been set, otherwise false.
    1510             :  */
    1511             : 
    1512      405210 : int OGRFeature::IsFieldSet(int iField) const
    1513             : 
    1514             : {
    1515      405210 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    1516      405210 :     if (iSpecialField >= 0)
    1517             :     {
    1518             :         // Special field value accessors.
    1519        1060 :         switch (iSpecialField)
    1520             :         {
    1521         799 :             case SPF_FID:
    1522         799 :                 return GetFID() != OGRNullFID;
    1523             : 
    1524         244 :             case SPF_OGR_GEOM_WKT:
    1525             :             case SPF_OGR_GEOMETRY:
    1526         244 :                 return GetGeomFieldCount() > 0 && papoGeometries[0] != nullptr;
    1527             : 
    1528           2 :             case SPF_OGR_STYLE:
    1529           2 :                 return GetStyleString() != nullptr;
    1530             : 
    1531          15 :             case SPF_OGR_GEOM_AREA:
    1532          15 :                 if (GetGeomFieldCount() == 0 || papoGeometries[0] == nullptr)
    1533           1 :                     return FALSE;
    1534             : 
    1535          14 :                 return OGR_G_Area(OGRGeometry::ToHandle(papoGeometries[0])) !=
    1536          14 :                        0.0;
    1537             : 
    1538           0 :             default:
    1539           0 :                 return FALSE;
    1540             :         }
    1541             :     }
    1542             :     else
    1543             :     {
    1544      404150 :         return !OGR_RawField_IsUnset(&pauFields[iField]);
    1545             :     }
    1546             : }
    1547             : 
    1548             : /************************************************************************/
    1549             : /*                          OGR_F_IsFieldSet()                          */
    1550             : /************************************************************************/
    1551             : 
    1552             : /**
    1553             :  * \brief Test if a field has ever been assigned a value or not.
    1554             :  *
    1555             :  * This function is the same as the C++ method OGRFeature::IsFieldSet().
    1556             :  *
    1557             :  * @param hFeat handle to the feature on which the field is.
    1558             :  * @param iField the field to test.
    1559             :  *
    1560             :  * @return TRUE if the field has been set, otherwise false.
    1561             :  */
    1562             : 
    1563      102613 : int OGR_F_IsFieldSet(OGRFeatureH hFeat, int iField)
    1564             : 
    1565             : {
    1566      102613 :     VALIDATE_POINTER1(hFeat, "OGR_F_IsFieldSet", 0);
    1567             : 
    1568      102613 :     const OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
    1569      102613 :     if (iField < 0 || iField >= poFeature->GetFieldCount())
    1570             :     {
    1571           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iField);
    1572           0 :         return FALSE;
    1573             :     }
    1574             : 
    1575      102613 :     return poFeature->IsFieldSet(iField);
    1576             : }
    1577             : 
    1578             : /************************************************************************/
    1579             : /*                             UnsetField()                             */
    1580             : /************************************************************************/
    1581             : 
    1582             : /**
    1583             :  * \brief Clear a field, marking it as unset.
    1584             :  *
    1585             :  * This method is the same as the C function OGR_F_UnsetField().
    1586             :  *
    1587             :  * @param iField the field to unset.
    1588             :  */
    1589             : 
    1590        9532 : void OGRFeature::UnsetField(int iField)
    1591             : 
    1592             : {
    1593        9532 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    1594             : 
    1595        9532 :     if (poFDefn == nullptr || !IsFieldSet(iField))
    1596        9449 :         return;
    1597             : 
    1598          83 :     if (!IsFieldNull(iField))
    1599             :     {
    1600          83 :         switch (poFDefn->GetType())
    1601             :         {
    1602           0 :             case OFTRealList:
    1603             :             case OFTIntegerList:
    1604             :             case OFTInteger64List:
    1605           0 :                 CPLFree(pauFields[iField].IntegerList.paList);
    1606           0 :                 break;
    1607             : 
    1608           5 :             case OFTStringList:
    1609           5 :                 CSLDestroy(pauFields[iField].StringList.paList);
    1610           5 :                 break;
    1611             : 
    1612          46 :             case OFTString:
    1613          46 :                 CPLFree(pauFields[iField].String);
    1614          46 :                 break;
    1615             : 
    1616           0 :             case OFTBinary:
    1617           0 :                 CPLFree(pauFields[iField].Binary.paData);
    1618           0 :                 break;
    1619             : 
    1620          32 :             default:
    1621          32 :                 break;
    1622             :         }
    1623             :     }
    1624             : 
    1625          83 :     OGR_RawField_SetUnset(&pauFields[iField]);
    1626             : }
    1627             : 
    1628             : /************************************************************************/
    1629             : /*                          OGR_F_UnsetField()                          */
    1630             : /************************************************************************/
    1631             : 
    1632             : /**
    1633             :  * \brief Clear a field, marking it as unset.
    1634             :  *
    1635             :  * This function is the same as the C++ method OGRFeature::UnsetField().
    1636             :  *
    1637             :  * @param hFeat handle to the feature on which the field is.
    1638             :  * @param iField the field to unset.
    1639             :  */
    1640             : 
    1641           5 : void OGR_F_UnsetField(OGRFeatureH hFeat, int iField)
    1642             : 
    1643             : {
    1644           5 :     VALIDATE_POINTER0(hFeat, "OGR_F_UnsetField");
    1645             : 
    1646           5 :     OGRFeature::FromHandle(hFeat)->UnsetField(iField);
    1647             : }
    1648             : 
    1649             : /************************************************************************/
    1650             : /*                            IsFieldNull()                             */
    1651             : /************************************************************************/
    1652             : 
    1653             : /**
    1654             :  * \brief Test if a field is null.
    1655             :  *
    1656             :  * This method is the same as the C function OGR_F_IsFieldNull().
    1657             :  *
    1658             :  * @param iField the field to test.
    1659             :  *
    1660             :  * @return TRUE if the field is null, otherwise false.
    1661             :  *
    1662             :  */
    1663             : 
    1664      278984 : bool OGRFeature::IsFieldNull(int iField) const
    1665             : 
    1666             : {
    1667      278984 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    1668      278984 :     if (iSpecialField >= 0)
    1669             :     {
    1670             :         // FIXME?
    1671           0 :         return false;
    1672             :     }
    1673             :     else
    1674             :     {
    1675      278984 :         return CPL_TO_BOOL(OGR_RawField_IsNull(&pauFields[iField]));
    1676             :     }
    1677             : }
    1678             : 
    1679             : /************************************************************************/
    1680             : /*                          OGR_F_IsFieldNull()                         */
    1681             : /************************************************************************/
    1682             : 
    1683             : /**
    1684             :  * \brief Test if a field is null.
    1685             :  *
    1686             :  * This function is the same as the C++ method OGRFeature::IsFieldNull().
    1687             :  *
    1688             :  * @param hFeat handle to the feature on which the field is.
    1689             :  * @param iField the field to test.
    1690             :  *
    1691             :  * @return TRUE if the field is null, otherwise false.
    1692             :  *
    1693             :  */
    1694             : 
    1695      101775 : int OGR_F_IsFieldNull(OGRFeatureH hFeat, int iField)
    1696             : 
    1697             : {
    1698      101775 :     VALIDATE_POINTER1(hFeat, "OGR_F_IsFieldNull", 0);
    1699             : 
    1700      101775 :     const OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
    1701      101775 :     if (iField < 0 || iField >= poFeature->GetFieldCount())
    1702             :     {
    1703           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iField);
    1704           0 :         return FALSE;
    1705             :     }
    1706             : 
    1707      101775 :     return poFeature->IsFieldNull(iField);
    1708             : }
    1709             : 
    1710             : /************************************************************************/
    1711             : /*                       IsFieldSetAndNull()                            */
    1712             : /************************************************************************/
    1713             : 
    1714             : /**
    1715             :  * \brief Test if a field is set and not null.
    1716             :  *
    1717             :  * This method is the same as the C function OGR_F_IsFieldSetAndNotNull().
    1718             :  *
    1719             :  * @param iField the field to test.
    1720             :  *
    1721             :  * @return TRUE if the field is set and not null, otherwise false.
    1722             :  *
    1723             :  */
    1724             : 
    1725      521870 : bool OGRFeature::IsFieldSetAndNotNull(int iField) const
    1726             : 
    1727             : {
    1728      521870 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    1729      521870 :     if (iSpecialField >= 0)
    1730             :     {
    1731        1060 :         return CPL_TO_BOOL(IsFieldSet(iField));
    1732             :     }
    1733             :     else
    1734             :     {
    1735      520810 :         return IsFieldSetAndNotNullUnsafe(iField);
    1736             :     }
    1737             : }
    1738             : 
    1739             : /************************************************************************/
    1740             : /*                      OGR_F_IsFieldSetAndNotNull()                    */
    1741             : /************************************************************************/
    1742             : 
    1743             : /**
    1744             :  * \brief Test if a field is set and not null.
    1745             :  *
    1746             :  * This function is the same as the C++ method
    1747             :  * OGRFeature::IsFieldSetAndNotNull().
    1748             :  *
    1749             :  * @param hFeat handle to the feature on which the field is.
    1750             :  * @param iField the field to test.
    1751             :  *
    1752             :  * @return TRUE if the field is set and not null, otherwise false.
    1753             :  *
    1754             :  */
    1755             : 
    1756        2403 : int OGR_F_IsFieldSetAndNotNull(OGRFeatureH hFeat, int iField)
    1757             : 
    1758             : {
    1759        2403 :     VALIDATE_POINTER1(hFeat, "OGR_F_IsFieldSetAndNotNull", 0);
    1760             : 
    1761        2403 :     OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
    1762             : 
    1763        2403 :     if (iField < 0 || iField >= poFeature->GetFieldCount())
    1764             :     {
    1765           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iField);
    1766           0 :         return FALSE;
    1767             :     }
    1768             : 
    1769        2403 :     return poFeature->IsFieldSetAndNotNull(iField);
    1770             : }
    1771             : 
    1772             : /************************************************************************/
    1773             : /*                             SetFieldNull()                           */
    1774             : /************************************************************************/
    1775             : 
    1776             : /**
    1777             :  * \brief Clear a field, marking it as null.
    1778             :  *
    1779             :  * This method is the same as the C function OGR_F_SetFieldNull().
    1780             :  *
    1781             :  * @param iField the field to set to null.
    1782             :  *
    1783             :  */
    1784             : 
    1785       52850 : void OGRFeature::SetFieldNull(int iField)
    1786             : 
    1787             : {
    1788       52850 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    1789             : 
    1790       52850 :     if (poFDefn == nullptr || IsFieldNull(iField))
    1791           0 :         return;
    1792             : 
    1793       52850 :     if (IsFieldSet(iField))
    1794             :     {
    1795          64 :         switch (poFDefn->GetType())
    1796             :         {
    1797           3 :             case OFTRealList:
    1798             :             case OFTIntegerList:
    1799             :             case OFTInteger64List:
    1800           3 :                 CPLFree(pauFields[iField].IntegerList.paList);
    1801           3 :                 break;
    1802             : 
    1803           1 :             case OFTStringList:
    1804           1 :                 CSLDestroy(pauFields[iField].StringList.paList);
    1805           1 :                 break;
    1806             : 
    1807           8 :             case OFTString:
    1808           8 :                 CPLFree(pauFields[iField].String);
    1809           8 :                 break;
    1810             : 
    1811           1 :             case OFTBinary:
    1812           1 :                 CPLFree(pauFields[iField].Binary.paData);
    1813           1 :                 break;
    1814             : 
    1815          51 :             default:
    1816          51 :                 break;
    1817             :         }
    1818             :     }
    1819             : 
    1820       52850 :     OGR_RawField_SetNull(&pauFields[iField]);
    1821             : }
    1822             : 
    1823             : /************************************************************************/
    1824             : /*                          OGR_F_SetFieldNull()                        */
    1825             : /************************************************************************/
    1826             : 
    1827             : /**
    1828             :  * \brief Clear a field, marking it as null.
    1829             :  *
    1830             :  * This function is the same as the C++ method OGRFeature::SetFieldNull().
    1831             :  *
    1832             :  * @param hFeat handle to the feature on which the field is.
    1833             :  * @param iField the field to set to null.
    1834             :  *
    1835             :  */
    1836             : 
    1837          47 : void OGR_F_SetFieldNull(OGRFeatureH hFeat, int iField)
    1838             : 
    1839             : {
    1840          47 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldNull");
    1841             : 
    1842          47 :     OGRFeature::FromHandle(hFeat)->SetFieldNull(iField);
    1843             : }
    1844             : 
    1845             : /************************************************************************/
    1846             : /*                           operator[]                                */
    1847             : /************************************************************************/
    1848             : 
    1849             : /**
    1850             :  * \brief Return a field value.
    1851             :  *
    1852             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1. This is not
    1853             :  *               checked by the method !
    1854             :  *
    1855             :  * @return the field value.
    1856             :  */
    1857           0 : const OGRFeature::FieldValue OGRFeature::operator[](int iField) const
    1858             : {
    1859           0 :     return {this, iField};
    1860             : }
    1861             : 
    1862             : /**
    1863             :  * \brief Return a field value.
    1864             :  *
    1865             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1. This is not
    1866             :  *               checked by the method !
    1867             :  *
    1868             :  * @return the field value.
    1869             :  */
    1870          20 : OGRFeature::FieldValue OGRFeature::operator[](int iField)
    1871             : {
    1872          20 :     return {this, iField};
    1873             : }
    1874             : 
    1875             : /**
    1876             :  * \brief Return a field value.
    1877             :  *
    1878             :  * @param pszFieldName field name
    1879             :  *
    1880             :  * @return the field value, or throw a FieldNotFoundException if not found.
    1881             :  */
    1882             : const OGRFeature::FieldValue
    1883           0 : OGRFeature::operator[](const char *pszFieldName) const
    1884             : {
    1885           0 :     int iField = GetFieldIndex(pszFieldName);
    1886           0 :     if (iField < 0)
    1887           0 :         throw FieldNotFoundException();
    1888           0 :     return {this, iField};
    1889             : }
    1890             : 
    1891             : /**
    1892             :  * \brief Return a field value.
    1893             :  *
    1894             :  * @param pszFieldName field name
    1895             :  *
    1896             :  * @return the field value, or throw a FieldNotFoundException if not found.
    1897             :  */
    1898          28 : OGRFeature::FieldValue OGRFeature::operator[](const char *pszFieldName)
    1899             : {
    1900          28 :     int iField = GetFieldIndex(pszFieldName);
    1901          28 :     if (iField < 0)
    1902           1 :         throw FieldNotFoundException();
    1903          27 :     return {this, iField};
    1904             : }
    1905             : 
    1906             : /************************************************************************/
    1907             : /*                           GetRawFieldRef()                           */
    1908             : /************************************************************************/
    1909             : 
    1910             : /**
    1911             :  * \fn OGRField *OGRFeature::GetRawFieldRef( int iField );
    1912             :  *
    1913             :  * \brief Fetch a pointer to the internal field value given the index.
    1914             :  *
    1915             :  * This method is the same as the C function OGR_F_GetRawFieldRef().
    1916             :  *
    1917             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    1918             :  *
    1919             :  * @return the returned pointer is to an internal data structure, and should
    1920             :  * not be freed, or modified.
    1921             :  */
    1922             : 
    1923             : /**
    1924             :  * \fn const OGRField *OGRFeature::GetRawFieldRef( int iField ) const;
    1925             :  *
    1926             :  * \brief Fetch a pointer to the internal field value given the index.
    1927             :  *
    1928             :  * This method is the same as the C function OGR_F_GetRawFieldRef().
    1929             :  *
    1930             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    1931             :  *
    1932             :  * @return the returned pointer is to an internal data structure, and should
    1933             :  * not be freed, or modified.
    1934             :  */
    1935             : 
    1936             : /************************************************************************/
    1937             : /*                        OGR_F_GetRawFieldRef()                        */
    1938             : /************************************************************************/
    1939             : 
    1940             : /**
    1941             :  * \brief Fetch a handle to the internal field value given the index.
    1942             :  *
    1943             :  * This function is the same as the C++ method OGRFeature::GetRawFieldRef().
    1944             :  *
    1945             :  * @param hFeat handle to the feature on which field is found.
    1946             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    1947             :  *
    1948             :  * @return the returned handle is to an internal data structure, and should
    1949             :  * not be freed, or modified.
    1950             :  */
    1951             : 
    1952           0 : OGRField *OGR_F_GetRawFieldRef(OGRFeatureH hFeat, int iField)
    1953             : 
    1954             : {
    1955           0 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetRawFieldRef", nullptr);
    1956             : 
    1957           0 :     return OGRFeature::FromHandle(hFeat)->GetRawFieldRef(iField);
    1958             : }
    1959             : 
    1960             : /************************************************************************/
    1961             : /*                         GetFieldAsInteger()                          */
    1962             : /************************************************************************/
    1963             : 
    1964             : /**
    1965             :  * \fn OGRFeature::GetFieldAsInteger( const char* pszFName ) const
    1966             :  * \brief Fetch field value as integer.
    1967             :  *
    1968             :  * OFTString features will be translated using atoi().  OFTReal fields
    1969             :  * will be cast to integer. OFTInteger64 are demoted to 32 bit, with
    1970             :  * clamping if out-of-range. Other field types, or errors will result in
    1971             :  * a return value of zero.
    1972             :  *
    1973             :  * @param pszFName the name of the field to fetch.
    1974             :  *
    1975             :  * @return the field value.
    1976             :  */
    1977             : 
    1978             : /**
    1979             :  * \brief Fetch field value as integer.
    1980             :  *
    1981             :  * OFTString features will be translated using atoi().  OFTReal fields
    1982             :  * will be cast to integer. OFTInteger64 are demoted to 32 bit, with
    1983             :  * clamping if out-of-range. Other field types, or errors will result in
    1984             :  * a return value of zero.
    1985             :  *
    1986             :  * This method is the same as the C function OGR_F_GetFieldAsInteger().
    1987             :  *
    1988             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    1989             :  *
    1990             :  * @return the field value.
    1991             :  */
    1992             : 
    1993      173381 : int OGRFeature::GetFieldAsInteger(int iField) const
    1994             : 
    1995             : {
    1996      173381 :     int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    1997      173381 :     if (iSpecialField >= 0)
    1998             :     {
    1999             :         // Special field value accessors.
    2000          19 :         switch (iSpecialField)
    2001             :         {
    2002          19 :             case SPF_FID:
    2003             :             {
    2004          38 :                 const int nVal = nFID > INT_MAX   ? INT_MAX
    2005          19 :                                  : nFID < INT_MIN ? INT_MIN
    2006          19 :                                                   : static_cast<int>(nFID);
    2007             : 
    2008          19 :                 if (nVal != nFID)
    2009             :                 {
    2010           0 :                     CPLError(CE_Warning, CPLE_AppDefined,
    2011             :                              "Field %s.FID: Integer overflow occurred when "
    2012             :                              "trying to return 64 bit integer %" PRId64
    2013             :                              ". Use GetFieldAsInteger64() instead",
    2014           0 :                              poDefn->GetName(), static_cast<int64_t>(nVal));
    2015             :                 }
    2016          19 :                 return nVal;
    2017             :             }
    2018             : 
    2019           0 :             case SPF_OGR_GEOM_AREA:
    2020           0 :                 if (GetGeomFieldCount() == 0 || papoGeometries[0] == nullptr)
    2021           0 :                     return 0;
    2022             :                 return static_cast<int>(
    2023           0 :                     OGR_G_Area(OGRGeometry::ToHandle(papoGeometries[0])));
    2024             : 
    2025           0 :             default:
    2026           0 :                 return 0;
    2027             :         }
    2028             :     }
    2029             : 
    2030      173362 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    2031             : 
    2032      173362 :     if (poFDefn == nullptr)
    2033           4 :         return 0;
    2034             : 
    2035      173358 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    2036       14117 :         return 0;
    2037             : 
    2038      159241 :     const OGRFieldType eType = poFDefn->GetType();
    2039      159241 :     if (eType == OFTInteger)
    2040             :     {
    2041      130000 :         return pauFields[iField].Integer;
    2042             :     }
    2043       29241 :     else if (eType == OFTInteger64)
    2044             :     {
    2045         143 :         const GIntBig nVal64 = pauFields[iField].Integer64;
    2046         284 :         const int nVal = nVal64 > INT_MAX   ? INT_MAX
    2047         141 :                          : nVal64 < INT_MIN ? INT_MIN
    2048             :                                             : static_cast<int>(nVal64);
    2049             : 
    2050         143 :         if (nVal != nVal64)
    2051             :         {
    2052           4 :             CPLError(CE_Warning, CPLE_AppDefined,
    2053             :                      "Field %s.%s: Integer overflow occurred when trying to "
    2054             :                      "return 64 bit integer %" PRId64
    2055             :                      ". Use GetFieldAsInteger64() instead",
    2056           2 :                      poDefn->GetName(), poFDefn->GetNameRef(),
    2057             :                      static_cast<int64_t>(nVal64));
    2058             :         }
    2059         143 :         return nVal;
    2060             :     }
    2061       29098 :     else if (eType == OFTReal)
    2062             :     {
    2063          22 :         return static_cast<int>(pauFields[iField].Real);
    2064             :     }
    2065       29076 :     else if (eType == OFTString)
    2066             :     {
    2067       29076 :         if (pauFields[iField].String == nullptr)
    2068           0 :             return 0;
    2069             :         else
    2070       29076 :             return atoi(pauFields[iField].String);
    2071             :     }
    2072             : 
    2073           0 :     return 0;
    2074             : }
    2075             : 
    2076             : /************************************************************************/
    2077             : /*                      OGR_F_GetFieldAsInteger()                       */
    2078             : /************************************************************************/
    2079             : 
    2080             : /**
    2081             :  * \brief Fetch field value as integer.
    2082             :  *
    2083             :  * OFTString features will be translated using atoi().  OFTReal fields
    2084             :  * will be cast to integer.   Other field types, or errors will result in
    2085             :  * a return value of zero.
    2086             :  *
    2087             :  * This function is the same as the C++ method OGRFeature::GetFieldAsInteger().
    2088             :  *
    2089             :  * @param hFeat handle to the feature that owned the field.
    2090             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    2091             :  *
    2092             :  * @return the field value.
    2093             :  */
    2094             : 
    2095       88354 : int OGR_F_GetFieldAsInteger(OGRFeatureH hFeat, int iField)
    2096             : 
    2097             : {
    2098       88354 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsInteger", 0);
    2099             : 
    2100       88354 :     return OGRFeature::FromHandle(hFeat)->GetFieldAsInteger(iField);
    2101             : }
    2102             : 
    2103             : /************************************************************************/
    2104             : /*                        GetFieldAsInteger64()                         */
    2105             : /************************************************************************/
    2106             : 
    2107             : /**
    2108             :  * \fn OGRFeature::GetFieldAsInteger64( const char* pszFName ) const
    2109             :  * \brief Fetch field value as integer 64 bit.
    2110             :  *
    2111             :  * OFTInteger are promoted to 64 bit.
    2112             :  * OFTString features will be translated using CPLAtoGIntBig().  OFTReal fields
    2113             :  * will be cast to integer.   Other field types, or errors will result in
    2114             :  * a return value of zero.
    2115             :  *
    2116             :  * @param pszFName the name of the field to fetch.
    2117             :  *
    2118             :  * @return the field value.
    2119             :  */
    2120             : 
    2121             : /**
    2122             :  * \brief Fetch field value as integer 64 bit.
    2123             :  *
    2124             :  * OFTInteger are promoted to 64 bit.
    2125             :  * OFTString features will be translated using CPLAtoGIntBig().  OFTReal fields
    2126             :  * will be cast to integer.   Other field types, or errors will result in
    2127             :  * a return value of zero.
    2128             :  *
    2129             :  * This method is the same as the C function OGR_F_GetFieldAsInteger64().
    2130             :  *
    2131             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    2132             :  *
    2133             :  * @return the field value.
    2134             :  */
    2135             : 
    2136       29296 : GIntBig OGRFeature::GetFieldAsInteger64(int iField) const
    2137             : 
    2138             : {
    2139       29296 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    2140       29296 :     if (iSpecialField >= 0)
    2141             :     {
    2142             :         // Special field value accessors.
    2143         801 :         switch (iSpecialField)
    2144             :         {
    2145         801 :             case SPF_FID:
    2146         801 :                 return nFID;
    2147             : 
    2148           0 :             case SPF_OGR_GEOM_AREA:
    2149           0 :                 if (GetGeomFieldCount() == 0 || papoGeometries[0] == nullptr)
    2150           0 :                     return 0;
    2151           0 :                 return static_cast<int>(
    2152           0 :                     OGR_G_Area(OGRGeometry::ToHandle(papoGeometries[0])));
    2153             : 
    2154           0 :             default:
    2155           0 :                 return 0;
    2156             :         }
    2157             :     }
    2158             : 
    2159       28495 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    2160             : 
    2161       28495 :     if (poFDefn == nullptr)
    2162           0 :         return 0;
    2163             : 
    2164       28495 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    2165          25 :         return 0;
    2166             : 
    2167       28470 :     OGRFieldType eType = poFDefn->GetType();
    2168       28470 :     if (eType == OFTInteger)
    2169             :     {
    2170       11695 :         return static_cast<GIntBig>(pauFields[iField].Integer);
    2171             :     }
    2172       16775 :     else if (eType == OFTInteger64)
    2173             :     {
    2174       16671 :         return pauFields[iField].Integer64;
    2175             :     }
    2176         104 :     else if (eType == OFTReal)
    2177             :     {
    2178           1 :         return static_cast<GIntBig>(pauFields[iField].Real);
    2179             :     }
    2180         103 :     else if (eType == OFTString)
    2181             :     {
    2182         103 :         if (pauFields[iField].String == nullptr)
    2183           0 :             return 0;
    2184             :         else
    2185             :         {
    2186         103 :             return CPLAtoGIntBigEx(pauFields[iField].String, TRUE, nullptr);
    2187             :         }
    2188             :     }
    2189             : 
    2190           0 :     return 0;
    2191             : }
    2192             : 
    2193             : /************************************************************************/
    2194             : /*                      OGR_F_GetFieldAsInteger64()                     */
    2195             : /************************************************************************/
    2196             : 
    2197             : /**
    2198             :  * \brief Fetch field value as integer 64 bit.
    2199             :  *
    2200             :  * OFTInteger are promoted to 64 bit.
    2201             :  * OFTString features will be translated using CPLAtoGIntBig().  OFTReal fields
    2202             :  * will be cast to integer.   Other field types, or errors will result in
    2203             :  * a return value of zero.
    2204             :  *
    2205             :  * This function is the same as the C++ method
    2206             :  * OGRFeature::GetFieldAsInteger64().
    2207             :  *
    2208             :  * @param hFeat handle to the feature that owned the field.
    2209             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    2210             :  *
    2211             :  * @return the field value.
    2212             :  */
    2213             : 
    2214        1452 : GIntBig OGR_F_GetFieldAsInteger64(OGRFeatureH hFeat, int iField)
    2215             : 
    2216             : {
    2217        1452 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsInteger64", 0);
    2218             : 
    2219        1452 :     return OGRFeature::FromHandle(hFeat)->GetFieldAsInteger64(iField);
    2220             : }
    2221             : 
    2222             : /************************************************************************/
    2223             : /*                          GetFieldAsDouble()                          */
    2224             : /************************************************************************/
    2225             : 
    2226             : /**
    2227             :  * \fn OGRFeature::GetFieldAsDouble( const char* pszFName ) const
    2228             :  * \brief Fetch field value as a double.
    2229             :  *
    2230             :  * OFTString features will be translated using CPLAtof().  OFTInteger and
    2231             :  * OFTInteger64 fields will be cast to double.  Other field types, or errors
    2232             :  * will result in a return value of zero.
    2233             :  *
    2234             :  * @param pszFName the name of the field to fetch.
    2235             :  *
    2236             :  * @return the field value.
    2237             :  */
    2238             : 
    2239             : /**
    2240             :  * \brief Fetch field value as a double.
    2241             :  *
    2242             :  * OFTString features will be translated using CPLAtof().  OFTInteger and
    2243             :  * OFTInteger64 fields will be cast to double.  Other field types, or errors
    2244             :  * will result in a return value of zero.
    2245             :  *
    2246             :  * This method is the same as the C function OGR_F_GetFieldAsDouble().
    2247             :  *
    2248             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    2249             :  *
    2250             :  * @return the field value.
    2251             :  */
    2252             : 
    2253      133880 : double OGRFeature::GetFieldAsDouble(int iField) const
    2254             : 
    2255             : {
    2256      133880 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    2257      133880 :     if (iSpecialField >= 0)
    2258             :     {
    2259             :         // Special field value accessors.
    2260          25 :         switch (iSpecialField)
    2261             :         {
    2262           0 :             case SPF_FID:
    2263           0 :                 return static_cast<double>(GetFID());
    2264             : 
    2265          25 :             case SPF_OGR_GEOM_AREA:
    2266          25 :                 if (GetGeomFieldCount() == 0 || papoGeometries[0] == nullptr)
    2267           0 :                     return 0.0;
    2268          25 :                 return OGR_G_Area(OGRGeometry::ToHandle(papoGeometries[0]));
    2269             : 
    2270           0 :             default:
    2271           0 :                 return 0.0;
    2272             :         }
    2273             :     }
    2274             : 
    2275      133855 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    2276             : 
    2277      133855 :     if (poFDefn == nullptr)
    2278           5 :         return 0.0;
    2279             : 
    2280      133850 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    2281          96 :         return 0.0;
    2282             : 
    2283      133754 :     const OGRFieldType eType = poFDefn->GetType();
    2284      133754 :     if (eType == OFTReal)
    2285             :     {
    2286       69562 :         return pauFields[iField].Real;
    2287             :     }
    2288       64192 :     else if (eType == OFTInteger)
    2289             :     {
    2290          75 :         return pauFields[iField].Integer;
    2291             :     }
    2292       64117 :     else if (eType == OFTInteger64)
    2293             :     {
    2294         118 :         return static_cast<double>(pauFields[iField].Integer64);
    2295             :     }
    2296       63999 :     else if (eType == OFTString)
    2297             :     {
    2298       63999 :         if (pauFields[iField].String == nullptr)
    2299           0 :             return 0;
    2300             :         else
    2301       63999 :             return CPLAtof(pauFields[iField].String);
    2302             :     }
    2303             : 
    2304           0 :     return 0.0;
    2305             : }
    2306             : 
    2307             : /************************************************************************/
    2308             : /*                       OGR_F_GetFieldAsDouble()                       */
    2309             : /************************************************************************/
    2310             : 
    2311             : /**
    2312             :  * \brief Fetch field value as a double.
    2313             :  *
    2314             :  * OFTString features will be translated using CPLAtof().  OFTInteger fields
    2315             :  * will be cast to double.   Other field types, or errors will result in
    2316             :  * a return value of zero.
    2317             :  *
    2318             :  * This function is the same as the C++ method OGRFeature::GetFieldAsDouble().
    2319             :  *
    2320             :  * @param hFeat handle to the feature that owned the field.
    2321             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    2322             :  *
    2323             :  * @return the field value.
    2324             :  */
    2325             : 
    2326        2473 : double OGR_F_GetFieldAsDouble(OGRFeatureH hFeat, int iField)
    2327             : 
    2328             : {
    2329        2473 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsDouble", 0);
    2330             : 
    2331        2473 :     return OGRFeature::FromHandle(hFeat)->GetFieldAsDouble(iField);
    2332             : }
    2333             : 
    2334             : /************************************************************************/
    2335             : /*                      OGRFeatureFormatDateTimeBuffer()                */
    2336             : /************************************************************************/
    2337             : 
    2338        1362 : static void OGRFeatureFormatDateTimeBuffer(char *szTempBuffer, size_t nMaxSize,
    2339             :                                            int nYear, int nMonth, int nDay,
    2340             :                                            int nHour, int nMinute,
    2341             :                                            float fSecond, int nTZFlag)
    2342             : {
    2343        1362 :     const int ms = OGR_GET_MS(fSecond);
    2344        1362 :     if (ms != 0)
    2345         365 :         CPLsnprintf(szTempBuffer, nMaxSize, "%04d/%02d/%02d %02d:%02d:%06.3f",
    2346             :                     nYear, nMonth, nDay, nHour, nMinute,
    2347             :                     static_cast<double>(fSecond));
    2348             :     else  // Default format.
    2349             :     {
    2350         997 :         if (std::isnan(fSecond) || fSecond < 0.0f || fSecond > 62.0f)
    2351             :         {
    2352           0 :             fSecond = 0.0;
    2353           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    2354             :                      "OGRFeatureFormatDateTimeBuffer: fSecond is invalid.  "
    2355             :                      "Forcing '%f' to 0.0.",
    2356             :                      static_cast<double>(fSecond));
    2357             :         }
    2358         997 :         snprintf(szTempBuffer, nMaxSize, "%04d/%02d/%02d %02d:%02d:%02d", nYear,
    2359             :                  nMonth, nDay, nHour, nMinute, static_cast<int>(fSecond));
    2360             :     }
    2361             : 
    2362        1362 :     if (nTZFlag > 1)
    2363             :     {
    2364             :         char chSign;
    2365         439 :         const int nOffset = (nTZFlag - 100) * 15;
    2366         439 :         int nHours = static_cast<int>(nOffset / 60);  // Round towards zero.
    2367         439 :         const int nMinutes = std::abs(nOffset - nHours * 60);
    2368             : 
    2369         439 :         if (nOffset < 0)
    2370             :         {
    2371          55 :             chSign = '-';
    2372          55 :             nHours = std::abs(nHours);
    2373             :         }
    2374             :         else
    2375             :         {
    2376         384 :             chSign = '+';
    2377             :         }
    2378             : 
    2379         439 :         if (nMinutes == 0)
    2380         392 :             snprintf(szTempBuffer + strlen(szTempBuffer),
    2381         392 :                      nMaxSize - strlen(szTempBuffer), "%c%02d", chSign, nHours);
    2382             :         else
    2383          47 :             snprintf(szTempBuffer + strlen(szTempBuffer),
    2384          47 :                      nMaxSize - strlen(szTempBuffer), "%c%02d%02d", chSign,
    2385             :                      nHours, nMinutes);
    2386             :     }
    2387        1362 : }
    2388             : 
    2389             : /************************************************************************/
    2390             : /*                          GetFieldAsString()                          */
    2391             : /************************************************************************/
    2392             : 
    2393             : /**
    2394             :  * \fn OGRFeature::GetFieldAsString( const char* pszFName ) const
    2395             :  * \brief Fetch field value as a string.
    2396             :  *
    2397             :  * OFTReal, OFTInteger, OFTInteger64 fields will be translated to string using
    2398             :  * sprintf(), but not necessarily using the established formatting rules.
    2399             :  * OFTDateTime fields are formatted with "YYYY/MM/DD HH:MM:SS[.sss]+ZZ"
    2400             :  * (note this is not a ISO-8601 compliant string. Use
    2401             :  * GetFieldAsISO8601DateTime())
    2402             :  * OFTDate fields are formatted as "YYYY/MM/DD"
    2403             :  * OFTTime fields are formatted as "HH:MM:SS[.sss]"
    2404             :  * OFTRealList, OFTIntegerList, OFTInteger64List, OFTStringList fields are
    2405             :  * formatted as "(number_of_values:val1,val2,...,valN)"
    2406             :  * OFTBinary fields are formatted as an hexadecimal representation.
    2407             :  * Other field types, or errors will result in a return of an empty string.
    2408             :  *
    2409             :  * @param pszFName the name of the field to fetch.
    2410             :  *
    2411             :  * @return the field value.  This string is internal, and should not be
    2412             :  * modified, or freed.  Its lifetime may be very brief.
    2413             :  */
    2414             : 
    2415             : /**
    2416             :  * \brief Fetch field value as a string.
    2417             :  *
    2418             :  * OFTReal, OFTInteger, OFTInteger64 fields will be translated to string using
    2419             :  * sprintf(), but not necessarily using the established formatting rules.
    2420             :  * OFTDateTime fields are formatted with "YYYY/MM/DD HH:MM:SS[.sss]+ZZ"
    2421             :  * (note this is not a ISO-8601 compliant string. Use
    2422             :  * GetFieldAsISO8601DateTime())
    2423             :  * OFTDate fields are formatted as "YYYY/MM/DD"
    2424             :  * OFTTime fields are formatted as "HH:MM:SS[.sss]"
    2425             :  * OFTRealList, OFTIntegerList, OFTInteger64List, OFTStringList fields are
    2426             :  * formatted as "(number_of_values:val1,val2,...,valN)"
    2427             :  * OFTBinary fields are formatted as an hexadecimal representation.
    2428             :  * Other field types, or errors will result in a return of an empty string.
    2429             :  *
    2430             :  * This method is the same as the C function OGR_F_GetFieldAsString().
    2431             :  *
    2432             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    2433             :  *
    2434             :  * @return the field value.  This string is internal, and should not be
    2435             :  * modified, or freed.  Its lifetime may be very brief.
    2436             :  */
    2437             : 
    2438      248887 : const char *OGRFeature::GetFieldAsString(int iField) const
    2439             : 
    2440             : {
    2441      248887 :     CPLFree(m_pszTmpFieldValue);
    2442      248887 :     m_pszTmpFieldValue = nullptr;
    2443             : 
    2444      248887 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    2445      248887 :     if (iSpecialField >= 0)
    2446             :     {
    2447             :         // Special field value accessors.
    2448         273 :         switch (iSpecialField)
    2449             :         {
    2450           0 :             case SPF_FID:
    2451             :             {
    2452           0 :                 constexpr size_t MAX_SIZE = 20 + 1;
    2453           0 :                 m_pszTmpFieldValue = static_cast<char *>(CPLMalloc(MAX_SIZE));
    2454           0 :                 CPLsnprintf(m_pszTmpFieldValue, MAX_SIZE, CPL_FRMT_GIB,
    2455             :                             GetFID());
    2456           0 :                 return m_pszTmpFieldValue;
    2457             :             }
    2458             : 
    2459         268 :             case SPF_OGR_GEOMETRY:
    2460         268 :                 if (GetGeomFieldCount() > 0 && papoGeometries[0] != nullptr)
    2461         241 :                     return papoGeometries[0]->getGeometryName();
    2462             :                 else
    2463          27 :                     return "";
    2464             : 
    2465           3 :             case SPF_OGR_STYLE:
    2466           3 :                 if (GetStyleString() == nullptr)
    2467           0 :                     return "";
    2468             :                 else
    2469           3 :                     return GetStyleString();
    2470             : 
    2471           2 :             case SPF_OGR_GEOM_WKT:
    2472             :             {
    2473           2 :                 if (GetGeomFieldCount() == 0 || papoGeometries[0] == nullptr)
    2474           0 :                     return "";
    2475             : 
    2476           2 :                 if (papoGeometries[0]->exportToWkt(&m_pszTmpFieldValue) ==
    2477             :                     OGRERR_NONE)
    2478           2 :                     return m_pszTmpFieldValue;
    2479             :                 else
    2480           0 :                     return "";
    2481             :             }
    2482             : 
    2483           0 :             case SPF_OGR_GEOM_AREA:
    2484             :             {
    2485           0 :                 if (GetGeomFieldCount() == 0 || papoGeometries[0] == nullptr)
    2486           0 :                     return "";
    2487             : 
    2488           0 :                 constexpr size_t MAX_SIZE = 20 + 1;
    2489           0 :                 m_pszTmpFieldValue = static_cast<char *>(CPLMalloc(MAX_SIZE));
    2490           0 :                 CPLsnprintf(
    2491             :                     m_pszTmpFieldValue, MAX_SIZE, "%.16g",
    2492           0 :                     OGR_G_Area(OGRGeometry::ToHandle(papoGeometries[0])));
    2493           0 :                 return m_pszTmpFieldValue;
    2494             :             }
    2495             : 
    2496           0 :             default:
    2497           0 :                 return "";
    2498             :         }
    2499             :     }
    2500             : 
    2501      248614 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    2502             : 
    2503      248614 :     if (poFDefn == nullptr)
    2504           3 :         return "";
    2505             : 
    2506      248611 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    2507        6162 :         return "";
    2508             : 
    2509      242449 :     OGRFieldType eType = poFDefn->GetType();
    2510      242449 :     if (eType == OFTString)
    2511             :     {
    2512      222326 :         if (pauFields[iField].String == nullptr)
    2513           0 :             return "";
    2514             :         else
    2515      222326 :             return pauFields[iField].String;
    2516             :     }
    2517       20123 :     else if (eType == OFTInteger)
    2518             :     {
    2519        7856 :         constexpr size_t MAX_SIZE = 11 + 1;
    2520        7856 :         m_pszTmpFieldValue = static_cast<char *>(CPLMalloc(MAX_SIZE));
    2521        7856 :         snprintf(m_pszTmpFieldValue, MAX_SIZE, "%d", pauFields[iField].Integer);
    2522        7856 :         return m_pszTmpFieldValue;
    2523             :     }
    2524       12267 :     else if (eType == OFTInteger64)
    2525             :     {
    2526        1030 :         constexpr size_t MAX_SIZE = 20 + 1;
    2527        1030 :         m_pszTmpFieldValue = static_cast<char *>(CPLMalloc(MAX_SIZE));
    2528        1030 :         CPLsnprintf(m_pszTmpFieldValue, MAX_SIZE, CPL_FRMT_GIB,
    2529        1030 :                     pauFields[iField].Integer64);
    2530        1030 :         return m_pszTmpFieldValue;
    2531             :     }
    2532       11237 :     else if (eType == OFTReal)
    2533             :     {
    2534        2653 :         char szFormat[32] = {};
    2535        2653 :         constexpr int TEMP_BUFFER_SIZE = 80;
    2536        2653 :         char szTempBuffer[TEMP_BUFFER_SIZE] = {};
    2537             : 
    2538        2653 :         if (poFDefn->GetWidth() != 0)
    2539             :         {
    2540         707 :             snprintf(szFormat, sizeof(szFormat), "%%.%df",
    2541             :                      poFDefn->GetPrecision());
    2542             : 
    2543         707 :             CPLsnprintf(szTempBuffer, TEMP_BUFFER_SIZE, szFormat,
    2544         707 :                         pauFields[iField].Real);
    2545             :         }
    2546             :         else
    2547             :         {
    2548        1946 :             if (poFDefn->GetSubType() == OFSTFloat32)
    2549             :             {
    2550          21 :                 OGRFormatFloat(szTempBuffer, TEMP_BUFFER_SIZE,
    2551          21 :                                static_cast<float>(pauFields[iField].Real), -1,
    2552             :                                'g');
    2553             :             }
    2554             :             else
    2555             :             {
    2556        1925 :                 strcpy(szFormat, "%.15g");
    2557             : 
    2558        1925 :                 CPLsnprintf(szTempBuffer, TEMP_BUFFER_SIZE, szFormat,
    2559        1925 :                             pauFields[iField].Real);
    2560             :             }
    2561             :         }
    2562             : 
    2563        2653 :         m_pszTmpFieldValue = VSI_STRDUP_VERBOSE(szTempBuffer);
    2564        2653 :         if (m_pszTmpFieldValue == nullptr)
    2565           0 :             return "";
    2566        2653 :         return m_pszTmpFieldValue;
    2567             :     }
    2568        8584 :     else if (eType == OFTDateTime)
    2569             :     {
    2570             :         // "YYYY/MM/DD HH:MM:SS.sss+ZZ"
    2571        1354 :         constexpr size_t EXTRA_SPACE_FOR_NEGATIVE_OR_LARGE_YEARS = 5;
    2572        1354 :         constexpr size_t MAX_SIZE =
    2573             :             26 + EXTRA_SPACE_FOR_NEGATIVE_OR_LARGE_YEARS + 1;
    2574        1354 :         m_pszTmpFieldValue = static_cast<char *>(CPLMalloc(MAX_SIZE));
    2575        1354 :         OGRFeatureFormatDateTimeBuffer(
    2576        1354 :             m_pszTmpFieldValue, MAX_SIZE, pauFields[iField].Date.Year,
    2577        1354 :             pauFields[iField].Date.Month, pauFields[iField].Date.Day,
    2578        1354 :             pauFields[iField].Date.Hour, pauFields[iField].Date.Minute,
    2579        1354 :             pauFields[iField].Date.Second, pauFields[iField].Date.TZFlag);
    2580             : 
    2581        1354 :         return m_pszTmpFieldValue;
    2582             :     }
    2583        7230 :     else if (eType == OFTDate)
    2584             :     {
    2585         881 :         constexpr size_t EXTRA_SPACE_FOR_NEGATIVE_OR_LARGE_YEARS = 5;
    2586         881 :         constexpr size_t MAX_SIZE =
    2587             :             10 + EXTRA_SPACE_FOR_NEGATIVE_OR_LARGE_YEARS + 1;
    2588         881 :         m_pszTmpFieldValue = static_cast<char *>(CPLMalloc(MAX_SIZE));
    2589         881 :         snprintf(m_pszTmpFieldValue, MAX_SIZE, "%04d/%02d/%02d",
    2590         881 :                  pauFields[iField].Date.Year, pauFields[iField].Date.Month,
    2591         881 :                  pauFields[iField].Date.Day);
    2592         881 :         return m_pszTmpFieldValue;
    2593             :     }
    2594        6349 :     else if (eType == OFTTime)
    2595             :     {
    2596        5271 :         constexpr size_t EXTRA_SPACE_TO_MAKE_GCC_HAPPY = 2;
    2597        5271 :         constexpr size_t MAX_SIZE = 12 + EXTRA_SPACE_TO_MAKE_GCC_HAPPY + 1;
    2598        5271 :         m_pszTmpFieldValue = static_cast<char *>(CPLMalloc(MAX_SIZE));
    2599        5271 :         const int ms = OGR_GET_MS(pauFields[iField].Date.Second);
    2600        5271 :         if (ms != 0 || std::isnan(pauFields[iField].Date.Second))
    2601        5123 :             snprintf(m_pszTmpFieldValue, MAX_SIZE, "%02d:%02d:%06.3f",
    2602        5123 :                      pauFields[iField].Date.Hour, pauFields[iField].Date.Minute,
    2603        5123 :                      static_cast<double>(pauFields[iField].Date.Second));
    2604             :         else
    2605         148 :             snprintf(m_pszTmpFieldValue, MAX_SIZE, "%02d:%02d:%02d",
    2606         148 :                      pauFields[iField].Date.Hour, pauFields[iField].Date.Minute,
    2607         148 :                      static_cast<int>(pauFields[iField].Date.Second));
    2608             : 
    2609        5271 :         return m_pszTmpFieldValue;
    2610             :     }
    2611        1078 :     else if (eType == OFTIntegerList)
    2612             :     {
    2613         223 :         char szItem[32] = {};
    2614         223 :         const int nCount = pauFields[iField].IntegerList.nCount;
    2615         446 :         CPLString osBuffer;
    2616             : 
    2617         223 :         osBuffer.Printf("(%d:", nCount);
    2618         686 :         for (int i = 0; i < nCount; i++)
    2619             :         {
    2620         463 :             snprintf(szItem, sizeof(szItem), "%d",
    2621         463 :                      pauFields[iField].IntegerList.paList[i]);
    2622         463 :             if (i > 0)
    2623         240 :                 osBuffer += ',';
    2624         463 :             osBuffer += szItem;
    2625             :         }
    2626         223 :         osBuffer += ')';
    2627             : 
    2628         223 :         m_pszTmpFieldValue = VSI_STRDUP_VERBOSE(osBuffer.c_str());
    2629         223 :         if (m_pszTmpFieldValue == nullptr)
    2630           0 :             return "";
    2631         223 :         return m_pszTmpFieldValue;
    2632             :     }
    2633         855 :     else if (eType == OFTInteger64List)
    2634             :     {
    2635         155 :         char szItem[32] = {};
    2636         155 :         const int nCount = pauFields[iField].Integer64List.nCount;
    2637         310 :         CPLString osBuffer;
    2638             : 
    2639         155 :         osBuffer.Printf("(%d:", nCount);
    2640         339 :         for (int i = 0; i < nCount; i++)
    2641             :         {
    2642         184 :             CPLsnprintf(szItem, sizeof(szItem), CPL_FRMT_GIB,
    2643         184 :                         pauFields[iField].Integer64List.paList[i]);
    2644         184 :             if (i > 0)
    2645          29 :                 osBuffer += ',';
    2646         184 :             osBuffer += szItem;
    2647             :         }
    2648         155 :         osBuffer += ')';
    2649             : 
    2650         155 :         m_pszTmpFieldValue = VSI_STRDUP_VERBOSE(osBuffer.c_str());
    2651         155 :         if (m_pszTmpFieldValue == nullptr)
    2652           0 :             return "";
    2653         155 :         return m_pszTmpFieldValue;
    2654             :     }
    2655         700 :     else if (eType == OFTRealList)
    2656             :     {
    2657         185 :         char szItem[40] = {};
    2658         185 :         char szFormat[64] = {};
    2659         185 :         const int nCount = pauFields[iField].RealList.nCount;
    2660         185 :         const bool bIsFloat32 = poFDefn->GetSubType() == OFSTFloat32;
    2661         185 :         const bool bIsZeroWidth = poFDefn->GetWidth() == 0;
    2662             : 
    2663         185 :         if (!bIsZeroWidth)
    2664             :         {
    2665          10 :             snprintf(szFormat, sizeof(szFormat), "%%%d.%df",
    2666             :                      poFDefn->GetWidth(), poFDefn->GetPrecision());
    2667             :         }
    2668             :         else
    2669         175 :             strcpy(szFormat, "%.16g");
    2670             : 
    2671         370 :         CPLString osBuffer;
    2672             : 
    2673         185 :         osBuffer.Printf("(%d:", nCount);
    2674             : 
    2675         468 :         for (int i = 0; i < nCount; i++)
    2676             :         {
    2677         283 :             if (bIsFloat32 && bIsZeroWidth)
    2678             :             {
    2679          36 :                 OGRFormatFloat(
    2680             :                     szItem, sizeof(szItem),
    2681          36 :                     static_cast<float>(pauFields[iField].RealList.paList[i]),
    2682             :                     -1, 'g');
    2683             :             }
    2684             :             else
    2685             :             {
    2686         247 :                 CPLsnprintf(szItem, sizeof(szItem), szFormat,
    2687         247 :                             pauFields[iField].RealList.paList[i]);
    2688             :             }
    2689         283 :             if (i > 0)
    2690          98 :                 osBuffer += ',';
    2691         283 :             osBuffer += szItem;
    2692             :         }
    2693         185 :         osBuffer += ')';
    2694             : 
    2695         185 :         m_pszTmpFieldValue = VSI_STRDUP_VERBOSE(osBuffer.c_str());
    2696         185 :         if (m_pszTmpFieldValue == nullptr)
    2697           0 :             return "";
    2698         185 :         return m_pszTmpFieldValue;
    2699             :     }
    2700         515 :     else if (eType == OFTStringList)
    2701             :     {
    2702         190 :         const int nCount = pauFields[iField].StringList.nCount;
    2703             : 
    2704         380 :         CPLString osBuffer;
    2705             : 
    2706         190 :         osBuffer.Printf("(%d:", nCount);
    2707         470 :         for (int i = 0; i < nCount; i++)
    2708             :         {
    2709         280 :             const char *pszItem = pauFields[iField].StringList.paList[i];
    2710         280 :             if (i > 0)
    2711          90 :                 osBuffer += ',';
    2712         280 :             osBuffer += pszItem;
    2713             :         }
    2714         190 :         osBuffer += ')';
    2715             : 
    2716         190 :         m_pszTmpFieldValue = VSI_STRDUP_VERBOSE(osBuffer.c_str());
    2717         190 :         if (m_pszTmpFieldValue == nullptr)
    2718           0 :             return "";
    2719         190 :         return m_pszTmpFieldValue;
    2720             :     }
    2721         325 :     else if (eType == OFTBinary)
    2722             :     {
    2723         325 :         const int nCount = pauFields[iField].Binary.nCount;
    2724         325 :         m_pszTmpFieldValue =
    2725         325 :             CPLBinaryToHex(nCount, pauFields[iField].Binary.paData);
    2726         325 :         if (m_pszTmpFieldValue == nullptr)
    2727           0 :             return "";
    2728         325 :         return m_pszTmpFieldValue;
    2729             :     }
    2730             : 
    2731           0 :     return "";
    2732             : }
    2733             : 
    2734             : /************************************************************************/
    2735             : /*                       OGR_F_GetFieldAsString()                       */
    2736             : /************************************************************************/
    2737             : 
    2738             : /**
    2739             :  * \brief Fetch field value as a string.
    2740             :  *
    2741             :  * OFTReal and OFTInteger fields will be translated to string using
    2742             :  * sprintf(), but not necessarily using the established formatting rules.
    2743             :  * Other field types, or errors will result in a return value of zero.
    2744             :  *
    2745             :  * This function is the same as the C++ method OGRFeature::GetFieldAsString().
    2746             :  *
    2747             :  * @param hFeat handle to the feature that owned the field.
    2748             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    2749             :  *
    2750             :  * @return the field value.  This string is internal, and should not be
    2751             :  * modified, or freed.  Its lifetime may be very brief.
    2752             :  */
    2753             : 
    2754       12142 : const char *OGR_F_GetFieldAsString(OGRFeatureH hFeat, int iField)
    2755             : 
    2756             : {
    2757       12142 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsString", nullptr);
    2758             : 
    2759       12142 :     return OGRFeature::FromHandle(hFeat)->GetFieldAsString(iField);
    2760             : }
    2761             : 
    2762             : /************************************************************************/
    2763             : /*                     GetFieldAsISO8601DateTime()                      */
    2764             : /************************************************************************/
    2765             : 
    2766             : /* clang-format off */
    2767             : /**
    2768             :  * \fn OGRFeature::GetFieldAsISO8601DateTime( const char* pszFName, CSLConstList papszOptions ) const
    2769             :  * \brief Fetch OFTDateTime field value as a ISO8601 representation.
    2770             :  *
    2771             :  * Return a string like "YYYY-MM-DDTHH:MM:SS(.sss)?(Z|([+|-]HH:MM))?"
    2772             :  * Milliseconds are omitted if equal to zero.
    2773             :  * Other field types, or errors will result in a return of an empty string.
    2774             :  *
    2775             :  * @param pszFName the name of the field to fetch.
    2776             :  * @param papszOptions NULL terminated list of strings, or NULL.
    2777             :  * No options are defined currently.
    2778             :  *
    2779             :  * @return the field value.  This string is internal, and should not be
    2780             :  * modified, or freed.  Its lifetime may be very brief.
    2781             :  *
    2782             :  * @since GDAL 3.7
    2783             :  */
    2784             : /* clang-format on */
    2785             : 
    2786             : /**
    2787             :  * \brief Fetch OFTDateTime field value as a ISO8601 representation.
    2788             :  *
    2789             :  * Return a string like "YYYY-MM-DDTHH:MM:SS(.sss)?(Z|([+|-]HH:MM))?"
    2790             :  * Milliseconds are omitted if equal to zero.
    2791             :  * Other field types, or errors will result in a return of an empty string.
    2792             :  *
    2793             :  * This method is the same as the C function OGR_F_GetFieldAsISO8601DateTime().
    2794             :  *
    2795             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    2796             :  * @param papszOptions NULL terminated list of strings, or NULL.
    2797             :  * No options are defined currently.
    2798             :  *
    2799             :  * @return the field value.  This string is internal, and should not be
    2800             :  * modified, or freed.  Its lifetime may be very brief.
    2801             :  *
    2802             :  * @since GDAL 3.7
    2803             :  */
    2804             : 
    2805          64 : const char *OGRFeature::GetFieldAsISO8601DateTime(
    2806             :     int iField, CPL_UNUSED CSLConstList papszOptions) const
    2807             : 
    2808             : {
    2809          64 :     CPLFree(m_pszTmpFieldValue);
    2810          64 :     m_pszTmpFieldValue = nullptr;
    2811             : 
    2812          64 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    2813          64 :     if (iSpecialField >= 0)
    2814             :     {
    2815           0 :         return "";
    2816             :     }
    2817             : 
    2818          64 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    2819             : 
    2820          64 :     if (poFDefn == nullptr)
    2821           1 :         return "";
    2822             : 
    2823          63 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    2824           1 :         return "";
    2825             : 
    2826          62 :     OGRFieldType eType = poFDefn->GetType();
    2827          62 :     if (eType != OFTDateTime)
    2828           1 :         return "";
    2829             : 
    2830          61 :     m_pszTmpFieldValue =
    2831          61 :         static_cast<char *>(CPLMalloc(OGR_SIZEOF_ISO8601_DATETIME_BUFFER));
    2832          61 :     constexpr bool bAlwaysMillisecond = false;
    2833          61 :     OGRGetISO8601DateTime(&pauFields[iField], bAlwaysMillisecond,
    2834             :                           m_pszTmpFieldValue);
    2835          61 :     return m_pszTmpFieldValue;
    2836             :     ;
    2837             : }
    2838             : 
    2839             : /************************************************************************/
    2840             : /*                     OGR_F_GetFieldAsISO8601DateTime()                */
    2841             : /************************************************************************/
    2842             : 
    2843             : /**
    2844             :  * \brief Fetch OFTDateTime field value as a ISO8601 representation.
    2845             :  *
    2846             :  * Return a string like "YYYY-MM6DDTHH:MM:SS(.sss)?(Z|([+|-]HH:MM))?"
    2847             :  * Milliseconds are omitted if equal to zero.
    2848             :  * Other field types, or errors will result in a return of an empty string.
    2849             :  *
    2850             :  * This function is the same as the C++ method OGRFeature::GetFieldAsISO8601DateTime().
    2851             :  *
    2852             :  * @param hFeat handle to the feature that owned the field.
    2853             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    2854             :  * @param papszOptions NULL terminated list of strings, or NULL.
    2855             :  * No options are defined currently.
    2856             :  *
    2857             :  * @return the field value.  This string is internal, and should not be
    2858             :  * modified, or freed.  Its lifetime may be very brief.
    2859             :  *
    2860             :  * @since GDAL 3.7
    2861             :  */
    2862             : 
    2863           8 : const char *OGR_F_GetFieldAsISO8601DateTime(OGRFeatureH hFeat, int iField,
    2864             :                                             CSLConstList papszOptions)
    2865             : 
    2866             : {
    2867           8 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsISO8601DateTime", nullptr);
    2868             : 
    2869           8 :     return OGRFeature::FromHandle(hFeat)->GetFieldAsISO8601DateTime(
    2870           8 :         iField, papszOptions);
    2871             : }
    2872             : 
    2873             : /************************************************************************/
    2874             : /*                       GetFieldAsIntegerList()                        */
    2875             : /************************************************************************/
    2876             : 
    2877             : /* clang-format off */
    2878             : /**
    2879             :  * \fn OGRFeature::GetFieldAsIntegerList( const char* pszFName, int *pnCount ) const
    2880             :  * \brief Fetch field value as a list of integers.
    2881             :  *
    2882             :  * Currently this method only works for OFTIntegerList fields.
    2883             : 
    2884             :  * @param pszFName the name of the field to fetch.
    2885             :  * @param pnCount an integer to put the list count (number of integers) into.
    2886             :  *
    2887             :  * @return the field value.  This list is internal, and should not be
    2888             :  * modified, or freed.  Its lifetime may be very brief.  If *pnCount is zero
    2889             :  * on return the returned pointer may be NULL or non-NULL.
    2890             :  * OFTReal and OFTInteger fields will be translated to string using
    2891             :  * sprintf(), but not necessarily using the established formatting rules.
    2892             :  * Other field types, or errors will result in a return value of zero.
    2893             :  */
    2894             : /* clang-format on */
    2895             : 
    2896             : /**
    2897             :  * \brief Fetch field value as a list of integers.
    2898             :  *
    2899             :  * Currently this method only works for OFTIntegerList fields.
    2900             :  *
    2901             :  * This method is the same as the C function OGR_F_GetFieldAsIntegerList().
    2902             :  *
    2903             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    2904             :  * @param pnCount an integer to put the list count (number of integers) into.
    2905             :  *
    2906             :  * @return the field value.  This list is internal, and should not be
    2907             :  * modified, or freed.  Its lifetime may be very brief.  If *pnCount is zero
    2908             :  * on return the returned pointer may be NULL or non-NULL.
    2909             :  */
    2910             : 
    2911       12623 : const int *OGRFeature::GetFieldAsIntegerList(int iField, int *pnCount) const
    2912             : 
    2913             : {
    2914       12623 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    2915             : 
    2916       25228 :     if (poFDefn != nullptr && IsFieldSetAndNotNullUnsafe(iField) &&
    2917       12605 :         poFDefn->GetType() == OFTIntegerList)
    2918             :     {
    2919       12605 :         if (pnCount != nullptr)
    2920       12605 :             *pnCount = pauFields[iField].IntegerList.nCount;
    2921             : 
    2922       12605 :         return pauFields[iField].IntegerList.paList;
    2923             :     }
    2924             : 
    2925          18 :     if (pnCount != nullptr)
    2926          18 :         *pnCount = 0;
    2927             : 
    2928          18 :     return nullptr;
    2929             : }
    2930             : 
    2931             : /************************************************************************/
    2932             : /*                    OGR_F_GetFieldAsIntegerList()                     */
    2933             : /************************************************************************/
    2934             : 
    2935             : /**
    2936             :  * \brief Fetch field value as a list of integers.
    2937             :  *
    2938             :  * Currently this function only works for OFTIntegerList fields.
    2939             :  *
    2940             :  * This function is the same as the C++ method
    2941             :  * OGRFeature::GetFieldAsIntegerList().
    2942             :  *
    2943             :  * @param hFeat handle to the feature that owned the field.
    2944             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    2945             :  * @param pnCount an integer to put the list count (number of integers) into.
    2946             :  *
    2947             :  * @return the field value.  This list is internal, and should not be
    2948             :  * modified, or freed.  Its lifetime may be very brief.  If *pnCount is zero
    2949             :  * on return the returned pointer may be NULL or non-NULL.
    2950             :  */
    2951             : 
    2952         812 : const int *OGR_F_GetFieldAsIntegerList(OGRFeatureH hFeat, int iField,
    2953             :                                        int *pnCount)
    2954             : 
    2955             : {
    2956         812 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsIntegerList", nullptr);
    2957             : 
    2958         812 :     return OGRFeature::FromHandle(hFeat)->GetFieldAsIntegerList(iField,
    2959         812 :                                                                 pnCount);
    2960             : }
    2961             : 
    2962             : /************************************************************************/
    2963             : /*                      GetFieldAsInteger64List()                       */
    2964             : /************************************************************************/
    2965             : 
    2966             : /* clang-format off */
    2967             : /**
    2968             :  * \fn OGRFeature::GetFieldAsInteger64List( const char* pszFName, int *pnCount ) const
    2969             :  * \brief Fetch field value as a list of 64 bit integers.
    2970             :  *
    2971             :  * Currently this method only works for OFTInteger64List fields.
    2972             : 
    2973             :  * @param pszFName the name of the field to fetch.
    2974             :  * @param pnCount an integer to put the list count (number of integers) into.
    2975             :  *
    2976             :  * @return the field value.  This list is internal, and should not be
    2977             :  * modified, or freed.  Its lifetime may be very brief.  If *pnCount is zero
    2978             :  * on return the returned pointer may be NULL or non-NULL.
    2979             :  */
    2980             : /* clang-format on */
    2981             : 
    2982             : /**
    2983             :  * \brief Fetch field value as a list of 64 bit integers.
    2984             :  *
    2985             :  * Currently this method only works for OFTInteger64List fields.
    2986             :  *
    2987             :  * This method is the same as the C function OGR_F_GetFieldAsInteger64List().
    2988             :  *
    2989             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    2990             :  * @param pnCount an integer to put the list count (number of integers) into.
    2991             :  *
    2992             :  * @return the field value.  This list is internal, and should not be
    2993             :  * modified, or freed.  Its lifetime may be very brief.  If *pnCount is zero
    2994             :  * on return the returned pointer may be NULL or non-NULL.
    2995             :  */
    2996             : 
    2997       10902 : const GIntBig *OGRFeature::GetFieldAsInteger64List(int iField,
    2998             :                                                    int *pnCount) const
    2999             : 
    3000             : {
    3001       10902 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3002             : 
    3003       21804 :     if (poFDefn != nullptr && IsFieldSetAndNotNullUnsafe(iField) &&
    3004       10902 :         poFDefn->GetType() == OFTInteger64List)
    3005             :     {
    3006       10902 :         if (pnCount != nullptr)
    3007       10902 :             *pnCount = pauFields[iField].Integer64List.nCount;
    3008             : 
    3009       10902 :         return pauFields[iField].Integer64List.paList;
    3010             :     }
    3011             : 
    3012           0 :     if (pnCount != nullptr)
    3013           0 :         *pnCount = 0;
    3014             : 
    3015           0 :     return nullptr;
    3016             : }
    3017             : 
    3018             : /************************************************************************/
    3019             : /*                   OGR_F_GetFieldAsInteger64List()                    */
    3020             : /************************************************************************/
    3021             : 
    3022             : /**
    3023             :  * \brief Fetch field value as a list of 64 bit integers.
    3024             :  *
    3025             :  * Currently this function only works for OFTInteger64List fields.
    3026             :  *
    3027             :  * This function is the same as the C++ method
    3028             :  * OGRFeature::GetFieldAsInteger64List().
    3029             :  *
    3030             :  * @param hFeat handle to the feature that owned the field.
    3031             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3032             :  * @param pnCount an integer to put the list count (number of integers) into.
    3033             :  *
    3034             :  * @return the field value.  This list is internal, and should not be
    3035             :  * modified, or freed.  Its lifetime may be very brief.  If *pnCount is zero
    3036             :  * on return the returned pointer may be NULL or non-NULL.
    3037             :  */
    3038             : 
    3039         333 : const GIntBig *OGR_F_GetFieldAsInteger64List(OGRFeatureH hFeat, int iField,
    3040             :                                              int *pnCount)
    3041             : 
    3042             : {
    3043         333 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsInteger64List", nullptr);
    3044             : 
    3045         333 :     return OGRFeature::FromHandle(hFeat)->GetFieldAsInteger64List(iField,
    3046         333 :                                                                   pnCount);
    3047             : }
    3048             : 
    3049             : /************************************************************************/
    3050             : /*                        GetFieldAsDoubleList()                        */
    3051             : /************************************************************************/
    3052             : 
    3053             : /* clang-format off */
    3054             : /**
    3055             :  * \fn OGRFeature::GetFieldAsDoubleList( const char* pszFName, int *pnCount ) const
    3056             :  * \brief Fetch field value as a list of doubles.
    3057             :  *
    3058             :  * Currently this method only works for OFTRealList fields.
    3059             : 
    3060             :  * @param pszFName the name of the field to fetch.
    3061             :  * @param pnCount an integer to put the list count (number of doubles) into.
    3062             :  *
    3063             :  * @return the field value.  This list is internal, and should not be
    3064             :  * modified, or freed.  Its lifetime may be very brief.  If *pnCount is zero
    3065             :  * on return the returned pointer may be NULL or non-NULL.
    3066             :  */
    3067             : /* clang-format on */
    3068             : 
    3069             : /**
    3070             :  * \brief Fetch field value as a list of doubles.
    3071             :  *
    3072             :  * Currently this method only works for OFTRealList fields.
    3073             :  *
    3074             :  * This method is the same as the C function OGR_F_GetFieldAsDoubleList().
    3075             :  *
    3076             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3077             :  * @param pnCount an integer to put the list count (number of doubles) into.
    3078             :  *
    3079             :  * @return the field value.  This list is internal, and should not be
    3080             :  * modified, or freed.  Its lifetime may be very brief.  If *pnCount is zero
    3081             :  * on return the returned pointer may be NULL or non-NULL.
    3082             :  */
    3083             : 
    3084        6774 : const double *OGRFeature::GetFieldAsDoubleList(int iField, int *pnCount) const
    3085             : 
    3086             : {
    3087        6774 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3088             : 
    3089        8516 :     if (poFDefn != nullptr && IsFieldSetAndNotNullUnsafe(iField) &&
    3090        1742 :         poFDefn->GetType() == OFTRealList)
    3091             :     {
    3092        1742 :         if (pnCount != nullptr)
    3093        1742 :             *pnCount = pauFields[iField].RealList.nCount;
    3094             : 
    3095        1742 :         return pauFields[iField].RealList.paList;
    3096             :     }
    3097             : 
    3098        5032 :     if (pnCount != nullptr)
    3099        5032 :         *pnCount = 0;
    3100             : 
    3101        5032 :     return nullptr;
    3102             : }
    3103             : 
    3104             : /************************************************************************/
    3105             : /*                     OGR_F_GetFieldAsDoubleList()                     */
    3106             : /************************************************************************/
    3107             : 
    3108             : /**
    3109             :  * \brief Fetch field value as a list of doubles.
    3110             :  *
    3111             :  * Currently this function only works for OFTRealList fields.
    3112             :  *
    3113             :  * This function is the same as the C++ method
    3114             :  * OGRFeature::GetFieldAsDoubleList().
    3115             :  *
    3116             :  * @param hFeat handle to the feature that owned the field.
    3117             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3118             :  * @param pnCount an integer to put the list count (number of doubles) into.
    3119             :  *
    3120             :  * @return the field value.  This list is internal, and should not be
    3121             :  * modified, or freed.  Its lifetime may be very brief.  If *pnCount is zero
    3122             :  * on return the returned pointer may be NULL or non-NULL.
    3123             :  */
    3124             : 
    3125         676 : const double *OGR_F_GetFieldAsDoubleList(OGRFeatureH hFeat, int iField,
    3126             :                                          int *pnCount)
    3127             : 
    3128             : {
    3129         676 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsDoubleList", nullptr);
    3130             : 
    3131         676 :     return OGRFeature::FromHandle(hFeat)->GetFieldAsDoubleList(iField, pnCount);
    3132             : }
    3133             : 
    3134             : /************************************************************************/
    3135             : /*                        GetFieldAsStringList()                        */
    3136             : /************************************************************************/
    3137             : /**
    3138             :  * \fn OGRFeature::GetFieldAsStringList( const char* pszFName ) const
    3139             :  * \brief Fetch field value as a list of strings.
    3140             :  *
    3141             :  * Currently this method only works for OFTStringList fields.
    3142             :  *
    3143             :  * The returned list is terminated by a NULL pointer. The number of
    3144             :  * elements can also be calculated using CSLCount().
    3145             :  *
    3146             :  * @param pszFName the name of the field to fetch.
    3147             :  *
    3148             :  * @return the field value.  This list is internal, and should not be
    3149             :  * modified, or freed.  Its lifetime may be very brief.
    3150             :  */
    3151             : 
    3152             : /**
    3153             :  * \brief Fetch field value as a list of strings.
    3154             :  *
    3155             :  * Currently this method only works for OFTStringList fields.
    3156             :  *
    3157             :  * The returned list is terminated by a NULL pointer. The number of
    3158             :  * elements can also be calculated using CSLCount().
    3159             :  *
    3160             :  * This method is the same as the C function OGR_F_GetFieldAsStringList().
    3161             :  *
    3162             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3163             :  *
    3164             :  * @return the field value.  This list is internal, and should not be
    3165             :  * modified, or freed.  Its lifetime may be very brief.
    3166             :  */
    3167             : 
    3168       11366 : char **OGRFeature::GetFieldAsStringList(int iField) const
    3169             : 
    3170             : {
    3171       11366 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3172             : 
    3173       11366 :     if (poFDefn == nullptr)
    3174           0 :         return nullptr;
    3175             : 
    3176       11366 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    3177          92 :         return nullptr;
    3178             : 
    3179       11274 :     if (poFDefn->GetType() == OFTStringList)
    3180             :     {
    3181       11274 :         return pauFields[iField].StringList.paList;
    3182             :     }
    3183             : 
    3184           0 :     return nullptr;
    3185             : }
    3186             : 
    3187             : /************************************************************************/
    3188             : /*                     OGR_F_GetFieldAsStringList()                     */
    3189             : /************************************************************************/
    3190             : 
    3191             : /**
    3192             :  * \brief Fetch field value as a list of strings.
    3193             :  *
    3194             :  * Currently this method only works for OFTStringList fields.
    3195             :  *
    3196             :  * The returned list is terminated by a NULL pointer. The number of
    3197             :  * elements can also be calculated using CSLCount().
    3198             :  *
    3199             :  * This function is the same as the C++ method
    3200             :  * OGRFeature::GetFieldAsStringList().
    3201             :  *
    3202             :  * @param hFeat handle to the feature that owned the field.
    3203             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3204             :  *
    3205             :  * @return the field value.  This list is internal, and should not be
    3206             :  * modified, or freed.  Its lifetime may be very brief.
    3207             :  */
    3208             : 
    3209         344 : char **OGR_F_GetFieldAsStringList(OGRFeatureH hFeat, int iField)
    3210             : 
    3211             : {
    3212         344 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsStringList", nullptr);
    3213             : 
    3214         344 :     return OGRFeature::FromHandle(hFeat)->GetFieldAsStringList(iField);
    3215             : }
    3216             : 
    3217             : /************************************************************************/
    3218             : /*                          GetFieldAsBinary()                          */
    3219             : /************************************************************************/
    3220             : 
    3221             : /**
    3222             :  * \brief Fetch field value as binary data.
    3223             :  *
    3224             :  * This method only works for OFTBinary and OFTString fields.
    3225             :  *
    3226             :  * This method is the same as the C function OGR_F_GetFieldAsBinary().
    3227             :  *
    3228             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3229             :  * @param pnBytes location to put the number of bytes returned.
    3230             :  *
    3231             :  * @return the field value.  This data is internal, and should not be
    3232             :  * modified, or freed.  Its lifetime may be very brief.
    3233             :  */
    3234             : 
    3235       29606 : GByte *OGRFeature::GetFieldAsBinary(int iField, int *pnBytes) const
    3236             : 
    3237             : {
    3238       29606 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3239             : 
    3240       29606 :     *pnBytes = 0;
    3241             : 
    3242       29606 :     if (poFDefn == nullptr)
    3243           0 :         return nullptr;
    3244             : 
    3245       29606 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    3246           6 :         return nullptr;
    3247             : 
    3248       29600 :     if (poFDefn->GetType() == OFTBinary)
    3249             :     {
    3250       29600 :         *pnBytes = pauFields[iField].Binary.nCount;
    3251       29600 :         return pauFields[iField].Binary.paData;
    3252             :     }
    3253           0 :     else if (poFDefn->GetType() == OFTString)
    3254             :     {
    3255           0 :         *pnBytes = static_cast<int>(strlen(pauFields[iField].String));
    3256           0 :         return reinterpret_cast<GByte *>(pauFields[iField].String);
    3257             :     }
    3258             : 
    3259           0 :     return nullptr;
    3260             : }
    3261             : 
    3262             : /************************************************************************/
    3263             : /*                       OGR_F_GetFieldAsBinary()                       */
    3264             : /************************************************************************/
    3265             : 
    3266             : /**
    3267             :  * \brief Fetch field value as binary.
    3268             :  *
    3269             :  * This method only works for OFTBinary and OFTString fields.
    3270             :  *
    3271             :  * This function is the same as the C++ method
    3272             :  * OGRFeature::GetFieldAsBinary().
    3273             :  *
    3274             :  * @param hFeat handle to the feature that owned the field.
    3275             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3276             :  * @param pnBytes location to place count of bytes returned.
    3277             :  *
    3278             :  * @return the field value.  This list is internal, and should not be
    3279             :  * modified, or freed.  Its lifetime may be very brief.
    3280             :  */
    3281             : 
    3282         315 : GByte *OGR_F_GetFieldAsBinary(OGRFeatureH hFeat, int iField, int *pnBytes)
    3283             : 
    3284             : {
    3285         315 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsBinary", nullptr);
    3286         315 :     VALIDATE_POINTER1(pnBytes, "OGR_F_GetFieldAsBinary", nullptr);
    3287             : 
    3288         315 :     return OGRFeature::FromHandle(hFeat)->GetFieldAsBinary(iField, pnBytes);
    3289             : }
    3290             : 
    3291             : /************************************************************************/
    3292             : /*                         GetFieldAsDateTime()                         */
    3293             : /************************************************************************/
    3294             : 
    3295             : /**
    3296             :  * \brief Fetch field value as date and time.
    3297             :  *
    3298             :  * Currently this method only works for OFTDate, OFTTime and OFTDateTime fields.
    3299             :  *
    3300             :  * This method is the same as the C function OGR_F_GetFieldAsDateTime().
    3301             :  *
    3302             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3303             :  * @param pnYear (including century)
    3304             :  * @param pnMonth (1-12)
    3305             :  * @param pnDay (1-31)
    3306             :  * @param pnHour (0-23)
    3307             :  * @param pnMinute (0-59)
    3308             :  * @param pfSecond (0-59 with millisecond accuracy)
    3309             :  * @param pnTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
    3310             :  *
    3311             :  * @return TRUE on success or FALSE on failure.
    3312             :  */
    3313             : 
    3314       14216 : int OGRFeature::GetFieldAsDateTime(int iField, int *pnYear, int *pnMonth,
    3315             :                                    int *pnDay, int *pnHour, int *pnMinute,
    3316             :                                    float *pfSecond, int *pnTZFlag) const
    3317             : 
    3318             : {
    3319       14216 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3320             : 
    3321       14216 :     if (poFDefn == nullptr)
    3322           0 :         return FALSE;
    3323             : 
    3324       14216 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    3325           1 :         return FALSE;
    3326             : 
    3327       16960 :     if (poFDefn->GetType() == OFTDate || poFDefn->GetType() == OFTTime ||
    3328        2745 :         poFDefn->GetType() == OFTDateTime)
    3329             :     {
    3330       14215 :         if (pnYear)
    3331       14207 :             *pnYear = pauFields[iField].Date.Year;
    3332       14215 :         if (pnMonth)
    3333       14154 :             *pnMonth = pauFields[iField].Date.Month;
    3334       14215 :         if (pnDay)
    3335       14154 :             *pnDay = pauFields[iField].Date.Day;
    3336       14215 :         if (pnHour)
    3337       14154 :             *pnHour = pauFields[iField].Date.Hour;
    3338       14215 :         if (pnMinute)
    3339       14154 :             *pnMinute = pauFields[iField].Date.Minute;
    3340       14215 :         if (pfSecond)
    3341       14154 :             *pfSecond = pauFields[iField].Date.Second;
    3342       14215 :         if (pnTZFlag)
    3343       14146 :             *pnTZFlag = pauFields[iField].Date.TZFlag;
    3344             : 
    3345       14215 :         return TRUE;
    3346             :     }
    3347             : 
    3348           0 :     return FALSE;
    3349             : }
    3350             : 
    3351             : /**
    3352             :  * \brief Fetch field value as date and time.
    3353             :  *
    3354             :  * Currently this method only works for OFTDate, OFTTime and OFTDateTime fields.
    3355             :  *
    3356             :  * This method is the same as the C function OGR_F_GetFieldAsDateTime().
    3357             :  *
    3358             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3359             :  * @param pnYear (including century)
    3360             :  * @param pnMonth (1-12)
    3361             :  * @param pnDay (1-31)
    3362             :  * @param pnHour (0-23)
    3363             :  * @param pnMinute (0-59)
    3364             :  * @param pnSecond (0-59)
    3365             :  * @param pnTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
    3366             :  *
    3367             :  * @return TRUE on success or FALSE on failure.
    3368             :  */
    3369             : 
    3370        5202 : int OGRFeature::GetFieldAsDateTime(int iField, int *pnYear, int *pnMonth,
    3371             :                                    int *pnDay, int *pnHour, int *pnMinute,
    3372             :                                    int *pnSecond, int *pnTZFlag) const
    3373             : {
    3374        5202 :     float fSecond = 0.0f;
    3375        5202 :     const bool bRet = CPL_TO_BOOL(GetFieldAsDateTime(
    3376             :         iField, pnYear, pnMonth, pnDay, pnHour, pnMinute, &fSecond, pnTZFlag));
    3377        5202 :     if (bRet && pnSecond)
    3378        5202 :         *pnSecond = static_cast<int>(fSecond);
    3379        5202 :     return bRet;
    3380             : }
    3381             : 
    3382             : /************************************************************************/
    3383             : /*                      OGR_F_GetFieldAsDateTime()                      */
    3384             : /************************************************************************/
    3385             : 
    3386             : /**
    3387             :  * \brief Fetch field value as date and time.
    3388             :  *
    3389             :  * Currently this method only works for OFTDate, OFTTime and OFTDateTime fields.
    3390             :  *
    3391             :  * This function is the same as the C++ method
    3392             :  * OGRFeature::GetFieldAsDateTime().
    3393             :  *
    3394             :  * @param hFeat handle to the feature that owned the field.
    3395             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3396             :  * @param pnYear (including century)
    3397             :  * @param pnMonth (1-12)
    3398             :  * @param pnDay (1-31)
    3399             :  * @param pnHour (0-23)
    3400             :  * @param pnMinute (0-59)
    3401             :  * @param pnSecond (0-59)
    3402             :  * @param pnTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
    3403             :  *
    3404             :  * @return TRUE on success or FALSE on failure.
    3405             :  *
    3406             :  * @see Use OGR_F_GetFieldAsDateTimeEx() for second with millisecond accuracy.
    3407             :  */
    3408             : 
    3409           0 : int OGR_F_GetFieldAsDateTime(OGRFeatureH hFeat, int iField, int *pnYear,
    3410             :                              int *pnMonth, int *pnDay, int *pnHour,
    3411             :                              int *pnMinute, int *pnSecond, int *pnTZFlag)
    3412             : 
    3413             : {
    3414           0 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsDateTime", 0);
    3415             : 
    3416           0 :     float fSecond = 0.0f;
    3417             :     const bool bRet =
    3418           0 :         CPL_TO_BOOL(OGRFeature::FromHandle(hFeat)->GetFieldAsDateTime(
    3419             :             iField, pnYear, pnMonth, pnDay, pnHour, pnMinute, &fSecond,
    3420             :             pnTZFlag));
    3421           0 :     if (bRet && pnSecond)
    3422           0 :         *pnSecond = static_cast<int>(fSecond);
    3423           0 :     return bRet;
    3424             : }
    3425             : 
    3426             : /************************************************************************/
    3427             : /*                     OGR_F_GetFieldAsDateTimeEx()                     */
    3428             : /************************************************************************/
    3429             : 
    3430             : /**
    3431             :  * \brief Fetch field value as date and time.
    3432             :  *
    3433             :  * Currently this method only works for OFTDate, OFTTime and OFTDateTime fields.
    3434             :  *
    3435             :  * This function is the same as the C++ method
    3436             :  * OGRFeature::GetFieldAsDateTime().
    3437             :  *
    3438             :  * @param hFeat handle to the feature that owned the field.
    3439             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3440             :  * @param pnYear (including century)
    3441             :  * @param pnMonth (1-12)
    3442             :  * @param pnDay (1-31)
    3443             :  * @param pnHour (0-23)
    3444             :  * @param pnMinute (0-59)
    3445             :  * @param pfSecond (0-59 with millisecond accuracy)
    3446             :  * @param pnTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
    3447             :  *
    3448             :  * @return TRUE on success or FALSE on failure.
    3449             :  */
    3450             : 
    3451          87 : int OGR_F_GetFieldAsDateTimeEx(OGRFeatureH hFeat, int iField, int *pnYear,
    3452             :                                int *pnMonth, int *pnDay, int *pnHour,
    3453             :                                int *pnMinute, float *pfSecond, int *pnTZFlag)
    3454             : 
    3455             : {
    3456          87 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsDateTimeEx", 0);
    3457             : 
    3458          87 :     return OGRFeature::FromHandle(hFeat)->GetFieldAsDateTime(
    3459          87 :         iField, pnYear, pnMonth, pnDay, pnHour, pnMinute, pfSecond, pnTZFlag);
    3460             : }
    3461             : 
    3462             : /************************************************************************/
    3463             : /*                        OGRFeatureGetIntegerValue()                   */
    3464             : /************************************************************************/
    3465             : 
    3466     1728690 : static int OGRFeatureGetIntegerValue(const OGRFeatureDefn *poDefn,
    3467             :                                      const OGRFieldDefn *poFDefn, int nValue)
    3468             : {
    3469     1728690 :     if (poFDefn->GetSubType() == OFSTBoolean && nValue != 0 && nValue != 1)
    3470             :     {
    3471           8 :         CPLError(CE_Warning, CPLE_AppDefined,
    3472             :                  "Field %s.%s: Only 0 or 1 should be passed for a OFSTBoolean "
    3473             :                  "subtype. Considering non-zero value %d as 1.",
    3474           4 :                  poDefn->GetName(), poFDefn->GetNameRef(), nValue);
    3475           4 :         nValue = 1;
    3476             :     }
    3477     1728680 :     else if (poFDefn->GetSubType() == OFSTInt16)
    3478             :     {
    3479        6190 :         if (nValue < -32768)
    3480             :         {
    3481           2 :             CPLError(CE_Warning, CPLE_AppDefined,
    3482             :                      "Field %s.%s: Out-of-range value for a OFSTInt16 subtype. "
    3483             :                      "Considering value %d as -32768.",
    3484           1 :                      poDefn->GetName(), poFDefn->GetNameRef(), nValue);
    3485           1 :             nValue = -32768;
    3486             :         }
    3487        6189 :         else if (nValue > 32767)
    3488             :         {
    3489           2 :             CPLError(CE_Warning, CPLE_AppDefined,
    3490             :                      "Field %s.%s: Out-of-range value for a OFSTInt16 subtype. "
    3491             :                      "Considering value %d as 32767.",
    3492           1 :                      poDefn->GetName(), poFDefn->GetNameRef(), nValue);
    3493           1 :             nValue = 32767;
    3494             :         }
    3495             :     }
    3496     1728690 :     return nValue;
    3497             : }
    3498             : 
    3499             : /************************************************************************/
    3500             : /*                        GetFieldAsSerializedJSon()                   */
    3501             : /************************************************************************/
    3502             : 
    3503             : /**
    3504             :  * \brief Fetch field value as a serialized JSon object.
    3505             :  *
    3506             :  * Currently this method only works for OFTString with OFSTJSON subtype,
    3507             :  * OFTStringList, OFTIntegerList,
    3508             :  * OFTInteger64List and OFTRealList
    3509             :  *
    3510             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3511             :  *
    3512             :  * @return a string that must be de-allocate with CPLFree()
    3513             :  */
    3514       15098 : char *OGRFeature::GetFieldAsSerializedJSon(int iField) const
    3515             : 
    3516             : {
    3517       15098 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    3518       15098 :     if (iSpecialField >= 0)
    3519             :     {
    3520           0 :         return nullptr;
    3521             :     }
    3522             : 
    3523       15098 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3524             : 
    3525       15098 :     if (poFDefn == nullptr)
    3526           0 :         return nullptr;
    3527             : 
    3528       15098 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    3529           0 :         return nullptr;
    3530             : 
    3531       15098 :     char *pszRet = nullptr;
    3532       15098 :     OGRFieldType eType = poFDefn->GetType();
    3533       15098 :     if (eType == OFTString && poFDefn->GetSubType() == OFSTJSON)
    3534             :     {
    3535          15 :         if (pauFields[iField].String[0] != '[' &&
    3536           5 :             pauFields[iField].String[0] != '{' &&
    3537           3 :             strcmp(pauFields[iField].String, "true") != 0 &&
    3538          12 :             strcmp(pauFields[iField].String, "false") != 0 &&
    3539           2 :             CPLGetValueType(pauFields[iField].String) == CPL_VALUE_STRING)
    3540             :         {
    3541           1 :             pszRet = CPLStrdup(('"' +
    3542           2 :                                 CPLString(pauFields[iField].String)
    3543           2 :                                     .replaceAll('\\', "\\\\")
    3544           2 :                                     .replaceAll('"', "\\\"") +
    3545             :                                 '"')
    3546             :                                    .c_str());
    3547             :         }
    3548             :         else
    3549             :         {
    3550           4 :             pszRet = CPLStrdup(pauFields[iField].String);
    3551             :         }
    3552             :     }
    3553       15093 :     else if (eType == OFTStringList)
    3554             :     {
    3555        5031 :         char **papszValues = GetFieldAsStringList(iField);
    3556        5031 :         if (papszValues == nullptr)
    3557             :         {
    3558           1 :             pszRet = CPLStrdup("[]");
    3559             :         }
    3560             :         else
    3561             :         {
    3562        5030 :             json_object *poObj = json_object_new_array();
    3563       15091 :             for (int i = 0; papszValues[i] != nullptr; i++)
    3564             :             {
    3565       10061 :                 json_object_array_add(poObj,
    3566       10061 :                                       json_object_new_string(papszValues[i]));
    3567             :             }
    3568        5030 :             pszRet = CPLStrdup(json_object_to_json_string(poObj));
    3569        5030 :             json_object_put(poObj);
    3570             :         }
    3571             :     }
    3572       10062 :     else if (eType == OFTIntegerList)
    3573             :     {
    3574        5030 :         json_object *poObj = json_object_new_array();
    3575        5030 :         int nCount = 0;
    3576        5030 :         const int *panValues = GetFieldAsIntegerList(iField, &nCount);
    3577        5030 :         if (poFDefn->GetSubType() == OFSTBoolean)
    3578             :         {
    3579          21 :             for (int i = 0; i < nCount; i++)
    3580             :             {
    3581          14 :                 json_object_array_add(
    3582          14 :                     poObj, json_object_new_boolean(panValues[i] != 0));
    3583             :             }
    3584             :         }
    3585             :         else
    3586             :         {
    3587       10073 :             for (int i = 0; i < nCount; i++)
    3588             :             {
    3589        5050 :                 json_object_array_add(poObj, json_object_new_int(panValues[i]));
    3590             :             }
    3591             :         }
    3592        5030 :         pszRet = CPLStrdup(json_object_to_json_string(poObj));
    3593        5030 :         json_object_put(poObj);
    3594             :     }
    3595        5032 :     else if (eType == OFTInteger64List)
    3596             :     {
    3597        5014 :         json_object *poObj = json_object_new_array();
    3598        5014 :         int nCount = 0;
    3599        5014 :         const GIntBig *panValues = GetFieldAsInteger64List(iField, &nCount);
    3600       10041 :         for (int i = 0; i < nCount; i++)
    3601             :         {
    3602        5027 :             json_object_array_add(poObj, json_object_new_int64(panValues[i]));
    3603             :         }
    3604        5014 :         pszRet = CPLStrdup(json_object_to_json_string(poObj));
    3605        5014 :         json_object_put(poObj);
    3606             :     }
    3607          18 :     else if (eType == OFTRealList)
    3608             :     {
    3609          18 :         json_object *poObj = json_object_new_array();
    3610          18 :         int nCount = 0;
    3611          18 :         const double *padfValues = GetFieldAsDoubleList(iField, &nCount);
    3612          54 :         for (int i = 0; i < nCount; i++)
    3613             :         {
    3614          36 :             json_object_array_add(poObj, json_object_new_double(padfValues[i]));
    3615             :         }
    3616          18 :         pszRet = CPLStrdup(json_object_to_json_string(poObj));
    3617          18 :         json_object_put(poObj);
    3618             :     }
    3619             : 
    3620       15098 :     return pszRet;
    3621             : }
    3622             : 
    3623             : /************************************************************************/
    3624             : /*                              SetField()                              */
    3625             : /************************************************************************/
    3626             : 
    3627             : /**
    3628             :  * \fn OGRFeature::SetField( const char* pszFName, int nValue )
    3629             :  * \brief Set field to integer value.
    3630             :  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
    3631             :  * fields will be assigned a string representation of the value, but not
    3632             :  * necessarily taking into account formatting constraints on this field.  Other
    3633             :  * field types may be unaffected.
    3634             :  *
    3635             :  * @note This method has only an effect on the in-memory feature object. If
    3636             :  * this object comes from a layer and the modifications must be serialized back
    3637             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    3638             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    3639             :  *
    3640             :  * @param pszFName the name of the field to set.
    3641             :  * @param nValue the value to assign.
    3642             :  */
    3643             : 
    3644             : /**
    3645             :  * \brief Set field to integer value.
    3646             :  *
    3647             :  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
    3648             :  * fields will be assigned a string representation of the value, but not
    3649             :  * necessarily taking into account formatting constraints on this field.  Other
    3650             :  * field types may be unaffected.
    3651             :  *
    3652             :  * This method is the same as the C function OGR_F_SetFieldInteger().
    3653             :  *
    3654             :  * @note This method has only an effect on the in-memory feature object. If
    3655             :  * this object comes from a layer and the modifications must be serialized back
    3656             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    3657             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    3658             :  *
    3659             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3660             :  * @param nValue the value to assign.
    3661             :  */
    3662             : 
    3663     1657260 : void OGRFeature::SetField(int iField, int nValue)
    3664             : 
    3665             : {
    3666     1657260 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3667             : 
    3668     1657260 :     if (poFDefn == nullptr)
    3669           0 :         return;
    3670             : 
    3671     1657260 :     OGRFieldType eType = poFDefn->GetType();
    3672     1657260 :     if (eType == OFTInteger)
    3673             :     {
    3674     3308360 :         pauFields[iField].Integer =
    3675     1654180 :             OGRFeatureGetIntegerValue(poDefn, poFDefn, nValue);
    3676     1654180 :         pauFields[iField].Set.nMarker2 = 0;
    3677     1654180 :         pauFields[iField].Set.nMarker3 = 0;
    3678             :     }
    3679        3077 :     else if (eType == OFTInteger64)
    3680             :     {
    3681        1194 :         pauFields[iField].Integer64 =
    3682        1194 :             OGRFeatureGetIntegerValue(poDefn, poFDefn, nValue);
    3683             :     }
    3684        1883 :     else if (eType == OFTReal)
    3685             :     {
    3686        1781 :         pauFields[iField].Real = nValue;
    3687             :     }
    3688         102 :     else if (eType == OFTIntegerList)
    3689             :     {
    3690           9 :         SetField(iField, 1, &nValue);
    3691             :     }
    3692          93 :     else if (eType == OFTInteger64List)
    3693             :     {
    3694           1 :         GIntBig nVal64 = nValue;
    3695           1 :         SetField(iField, 1, &nVal64);
    3696             :     }
    3697          92 :     else if (eType == OFTRealList)
    3698             :     {
    3699           1 :         double dfValue = nValue;
    3700           1 :         SetField(iField, 1, &dfValue);
    3701             :     }
    3702          91 :     else if (eType == OFTString)
    3703             :     {
    3704          86 :         char szTempBuffer[64] = {};
    3705             : 
    3706          86 :         snprintf(szTempBuffer, sizeof(szTempBuffer), "%d", nValue);
    3707             : 
    3708          86 :         if (IsFieldSetAndNotNullUnsafe(iField))
    3709          83 :             CPLFree(pauFields[iField].String);
    3710             : 
    3711          86 :         pauFields[iField].String = VSI_STRDUP_VERBOSE(szTempBuffer);
    3712          86 :         if (pauFields[iField].String == nullptr)
    3713             :         {
    3714           0 :             OGR_RawField_SetUnset(&pauFields[iField]);
    3715             :         }
    3716             :     }
    3717           5 :     else if (eType == OFTStringList)
    3718             :     {
    3719           1 :         char szTempBuffer[64] = {};
    3720             : 
    3721           1 :         snprintf(szTempBuffer, sizeof(szTempBuffer), "%d", nValue);
    3722           1 :         char *apszValues[2] = {szTempBuffer, nullptr};
    3723           1 :         SetField(iField, apszValues);
    3724             :     }
    3725             :     else
    3726             :     {
    3727             :         // Do nothing for other field types.
    3728             :     }
    3729             : }
    3730             : 
    3731             : /************************************************************************/
    3732             : /*                       OGR_F_SetFieldInteger()                        */
    3733             : /************************************************************************/
    3734             : 
    3735             : /**
    3736             :  * \brief Set field to integer value.
    3737             :  *
    3738             :  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
    3739             :  * fields will be assigned a string representation of the value, but not
    3740             :  * necessarily taking into account formatting constraints on this field.  Other
    3741             :  * field types may be unaffected.
    3742             :  *
    3743             :  * This function is the same as the C++ method OGRFeature::SetField().
    3744             :  *
    3745             :  * @note This method has only an effect on the in-memory feature object. If
    3746             :  * this object comes from a layer and the modifications must be serialized back
    3747             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    3748             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    3749             :  *
    3750             :  * @param hFeat handle to the feature that owned the field.
    3751             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3752             :  * @param nValue the value to assign.
    3753             :  */
    3754             : 
    3755        4815 : void OGR_F_SetFieldInteger(OGRFeatureH hFeat, int iField, int nValue)
    3756             : 
    3757             : {
    3758        4815 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldInteger");
    3759             : 
    3760        4815 :     OGRFeature::FromHandle(hFeat)->SetField(iField, nValue);
    3761             : }
    3762             : 
    3763             : /************************************************************************/
    3764             : /*                              SetField()                              */
    3765             : /************************************************************************/
    3766             : 
    3767             : /**
    3768             :  * \fn OGRFeature::SetField( const char* pszFName, GIntBig nValue )
    3769             :  * \brief Set field to 64 bit integer value.
    3770             :  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
    3771             :  * fields will be assigned a string representation of the value, but not
    3772             :  * necessarily taking into account formatting constraints on this field.  Other
    3773             :  * field types may be unaffected.
    3774             :  *
    3775             :  * @note This method has only an effect on the in-memory feature object. If
    3776             :  * this object comes from a layer and the modifications must be serialized back
    3777             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    3778             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    3779             :  *
    3780             :  * @param pszFName the name of the field to set.
    3781             :  * @param nValue the value to assign.
    3782             :  */
    3783             : 
    3784             : /**
    3785             :  * \brief Set field to 64 bit integer value.
    3786             :  *
    3787             :  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
    3788             :  * fields will be assigned a string representation of the value, but not
    3789             :  * necessarily taking into account formatting constraints on this field.  Other
    3790             :  * field types may be unaffected.
    3791             :  *
    3792             :  * This method is the same as the C function OGR_F_SetFieldInteger64().
    3793             :  *
    3794             :  * @note This method has only an effect on the in-memory feature object. If
    3795             :  * this object comes from a layer and the modifications must be serialized back
    3796             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    3797             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    3798             :  *
    3799             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3800             :  * @param nValue the value to assign.
    3801             :  */
    3802             : 
    3803       95243 : void OGRFeature::SetField(int iField, GIntBig nValue)
    3804             : 
    3805             : {
    3806       95243 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3807             : 
    3808       95243 :     if (poFDefn == nullptr)
    3809           0 :         return;
    3810             : 
    3811       95243 :     OGRFieldType eType = poFDefn->GetType();
    3812       95243 :     if (eType == OFTInteger)
    3813             :     {
    3814      173730 :         const int nVal32 = nValue < INT_MIN   ? INT_MIN
    3815       86865 :                            : nValue > INT_MAX ? INT_MAX
    3816             :                                               : static_cast<int>(nValue);
    3817             : 
    3818       86865 :         if (nVal32 != nValue)
    3819             :         {
    3820          12 :             CPLError(
    3821             :                 CE_Warning, CPLE_AppDefined,
    3822             :                 "Field %s.%s: integer overflow occurred when trying to set "
    3823             :                 "%" PRId64 " as 32 bit integer.",
    3824           6 :                 poDefn->GetName(), poFDefn->GetNameRef(),
    3825             :                 static_cast<int64_t>(nValue));
    3826             :         }
    3827       86865 :         SetField(iField, nVal32);
    3828             :     }
    3829        8378 :     else if (eType == OFTInteger64)
    3830             :     {
    3831        7615 :         pauFields[iField].Integer64 = nValue;
    3832             :     }
    3833         763 :     else if (eType == OFTReal)
    3834             :     {
    3835         643 :         pauFields[iField].Real = static_cast<double>(nValue);
    3836             :         // Values in the range [INT64_MAX - 1023, INT64_MAX - 1]
    3837             :         // get converted to a double that once cast to int64_t is
    3838             :         // INT64_MAX + 1 ...
    3839        1286 :         if (pauFields[iField].Real >=
    3840        1284 :                 static_cast<double>(std::numeric_limits<int64_t>::max()) ||
    3841         641 :             static_cast<GIntBig>(pauFields[iField].Real) != nValue)
    3842             :         {
    3843           4 :             CPLError(
    3844             :                 CE_Warning, CPLE_AppDefined,
    3845             :                 "Field %s.%s: Lossy conversion occurred when trying to set "
    3846             :                 "a real field from 64 bit integer value %" PRId64 ".",
    3847           2 :                 poDefn->GetName(), poFDefn->GetNameRef(),
    3848             :                 static_cast<int64_t>(nValue));
    3849             :         }
    3850             :     }
    3851         120 :     else if (eType == OFTIntegerList)
    3852             :     {
    3853           2 :         int nVal32 = nValue < INT_MIN   ? INT_MIN
    3854           1 :                      : nValue > INT_MAX ? INT_MAX
    3855             :                                         : static_cast<int>(nValue);
    3856             : 
    3857           1 :         if (nVal32 != nValue)
    3858             :         {
    3859           2 :             CPLError(
    3860             :                 CE_Warning, CPLE_AppDefined,
    3861             :                 "Field %s.%s: Integer overflow occurred when trying to set "
    3862             :                 "%" PRId64 " as 32 bit value.",
    3863           1 :                 poDefn->GetName(), poFDefn->GetNameRef(),
    3864             :                 static_cast<int64_t>(nValue));
    3865             :         }
    3866           1 :         SetField(iField, 1, &nVal32);
    3867             :     }
    3868         119 :     else if (eType == OFTInteger64List)
    3869             :     {
    3870          11 :         SetField(iField, 1, &nValue);
    3871             :     }
    3872         108 :     else if (eType == OFTRealList)
    3873             :     {
    3874           1 :         double dfValue = static_cast<double>(nValue);
    3875           1 :         SetField(iField, 1, &dfValue);
    3876             :     }
    3877         107 :     else if (eType == OFTString)
    3878             :     {
    3879         102 :         char szTempBuffer[64] = {};
    3880             : 
    3881         102 :         CPLsnprintf(szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB, nValue);
    3882             : 
    3883         102 :         if (IsFieldSetAndNotNullUnsafe(iField))
    3884           2 :             CPLFree(pauFields[iField].String);
    3885             : 
    3886         102 :         pauFields[iField].String = VSI_STRDUP_VERBOSE(szTempBuffer);
    3887         102 :         if (pauFields[iField].String == nullptr)
    3888             :         {
    3889           0 :             OGR_RawField_SetUnset(&pauFields[iField]);
    3890             :         }
    3891             :     }
    3892           5 :     else if (eType == OFTStringList)
    3893             :     {
    3894           1 :         char szTempBuffer[64] = {};
    3895             : 
    3896           1 :         CPLsnprintf(szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB, nValue);
    3897           1 :         char *apszValues[2] = {szTempBuffer, nullptr};
    3898           1 :         SetField(iField, apszValues);
    3899             :     }
    3900             :     else
    3901             :     {
    3902             :         // Do nothing for other field types.
    3903             :     }
    3904             : }
    3905             : 
    3906             : /************************************************************************/
    3907             : /*                      OGR_F_SetFieldInteger64()                       */
    3908             : /************************************************************************/
    3909             : 
    3910             : /**
    3911             :  * \brief Set field to 64 bit integer value.
    3912             :  *
    3913             :  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
    3914             :  * fields will be assigned a string representation of the value, but not
    3915             :  * necessarily taking into account formatting constraints on this field.  Other
    3916             :  * field types may be unaffected.
    3917             :  *
    3918             :  * This function is the same as the C++ method OGRFeature::SetField().
    3919             :  *
    3920             :  * @note This method has only an effect on the in-memory feature object. If
    3921             :  * this object comes from a layer and the modifications must be serialized back
    3922             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    3923             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    3924             :  *
    3925             :  * @param hFeat handle to the feature that owned the field.
    3926             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3927             :  * @param nValue the value to assign.
    3928             :  */
    3929             : 
    3930       84726 : void OGR_F_SetFieldInteger64(OGRFeatureH hFeat, int iField, GIntBig nValue)
    3931             : 
    3932             : {
    3933       84726 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldInteger64");
    3934             : 
    3935       84726 :     OGRFeature::FromHandle(hFeat)->SetField(iField, nValue);
    3936             : }
    3937             : 
    3938             : /************************************************************************/
    3939             : /*                              SetField()                              */
    3940             : /************************************************************************/
    3941             : 
    3942             : /**
    3943             :  * \fn OGRFeature::SetField( const char* pszFName, double dfValue )
    3944             :  * \brief Set field to double value.
    3945             :  *
    3946             :  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
    3947             :  * fields will be assigned a string representation of the value, but not
    3948             :  * necessarily taking into account formatting constraints on this field.  Other
    3949             :  * field types may be unaffected.
    3950             :  *
    3951             :  * @note This method has only an effect on the in-memory feature object. If
    3952             :  * this object comes from a layer and the modifications must be serialized back
    3953             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    3954             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    3955             :  *
    3956             :  * @param pszFName the name of the field to set.
    3957             :  * @param dfValue the value to assign.
    3958             :  */
    3959             : 
    3960             : /**
    3961             :  * \brief Set field to double value.
    3962             :  *
    3963             :  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
    3964             :  * fields will be assigned a string representation of the value, but not
    3965             :  * necessarily taking into account formatting constraints on this field.  Other
    3966             :  * field types may be unaffected.
    3967             :  *
    3968             :  * This method is the same as the C function OGR_F_SetFieldDouble().
    3969             :  *
    3970             :  * @note This method has only an effect on the in-memory feature object. If
    3971             :  * this object comes from a layer and the modifications must be serialized back
    3972             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    3973             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    3974             :  *
    3975             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    3976             :  * @param dfValue the value to assign.
    3977             :  */
    3978             : 
    3979       71297 : void OGRFeature::SetField(int iField, double dfValue)
    3980             : 
    3981             : {
    3982       71297 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3983             : 
    3984       71297 :     if (poFDefn == nullptr)
    3985           0 :         return;
    3986             : 
    3987       71297 :     const OGRFieldType eType = poFDefn->GetType();
    3988       71297 :     if (eType == OFTReal)
    3989             :     {
    3990             :         // if( poFDefn->GetSubType() == OFSTFloat32 &&
    3991             :         //     dfValue != (double)(float)dfValue )
    3992             :         // {
    3993             :         //     CPLError(CE_Warning, CPLE_AppDefined,
    3994             :         //              "Passed value cannot be exactly representing as "
    3995             :         //              "a single-precision floating point value.");
    3996             :         //     dfValue = (double)(float)dfValue;
    3997             :         // }
    3998       57386 :         pauFields[iField].Real = dfValue;
    3999             :     }
    4000       13911 :     else if (eType == OFTInteger)
    4001             :     {
    4002       13473 :         constexpr int nMin = std::numeric_limits<int>::min();
    4003       13473 :         if (std::isnan(dfValue))
    4004             :         {
    4005           2 :             pauFields[iField].Integer = nMin;
    4006           4 :             CPLError(
    4007             :                 CE_Warning, CPLE_AppDefined,
    4008             :                 "Field %s.%s: Lossy conversion occurred when trying to set "
    4009             :                 "32 bit integer field from real value %.17g.",
    4010           2 :                 poDefn->GetName(), poFDefn->GetNameRef(), dfValue);
    4011             :         }
    4012             :         else
    4013             :         {
    4014       13471 :             constexpr int nMax = std::numeric_limits<int>::max();
    4015       26942 :             const int nVal = dfValue < nMin   ? nMin
    4016       13471 :                              : dfValue > nMax ? nMax
    4017       13462 :                                               : static_cast<int>(dfValue);
    4018       26942 :             pauFields[iField].Integer =
    4019       13471 :                 OGRFeatureGetIntegerValue(poDefn, poFDefn, nVal);
    4020       13471 :             if (!(nVal == dfValue))
    4021             :             {
    4022          28 :                 CPLError(
    4023             :                     CE_Warning, CPLE_AppDefined,
    4024             :                     "Field %s.%s: Lossy conversion occurred when trying to set "
    4025             :                     "32 bit integer field from real value %.17g.",
    4026          14 :                     poDefn->GetName(), poFDefn->GetNameRef(), dfValue);
    4027             :             }
    4028             :         }
    4029       13473 :         pauFields[iField].Set.nMarker2 = 0;
    4030       13473 :         pauFields[iField].Set.nMarker3 = 0;
    4031             :     }
    4032         438 :     else if (eType == OFTInteger64)
    4033             :     {
    4034         400 :         constexpr auto nMin = std::numeric_limits<GIntBig>::min();
    4035         400 :         if (std::isnan(dfValue))
    4036             :         {
    4037           2 :             pauFields[iField].Integer64 = nMin;
    4038           4 :             CPLError(
    4039             :                 CE_Warning, CPLE_AppDefined,
    4040             :                 "Field %s.%s: Lossy conversion occurred when trying to set "
    4041             :                 "64 bit integer field from real value %.17g.",
    4042           2 :                 poDefn->GetName(), poFDefn->GetNameRef(), dfValue);
    4043             :         }
    4044             :         else
    4045             :         {
    4046         398 :             constexpr auto nMax = std::numeric_limits<GIntBig>::max();
    4047         796 :             const auto nVal = dfValue < static_cast<double>(nMin) ? nMin
    4048         398 :                               : dfValue > static_cast<double>(nMax)
    4049         398 :                                   ? nMax
    4050         398 :                                   : static_cast<GIntBig>(dfValue);
    4051         398 :             pauFields[iField].Integer64 = nVal;
    4052         398 :             if (!(static_cast<double>(nVal) == dfValue))
    4053             :             {
    4054           8 :                 CPLError(
    4055             :                     CE_Warning, CPLE_AppDefined,
    4056             :                     "Field %s.%s: Lossy conversion occurred when trying to set "
    4057             :                     "64 bit integer field from real value %.17g.",
    4058           4 :                     poDefn->GetName(), poFDefn->GetNameRef(), dfValue);
    4059             :             }
    4060             :         }
    4061         400 :         pauFields[iField].Set.nMarker3 = 0;
    4062             :     }
    4063          38 :     else if (eType == OFTRealList)
    4064             :     {
    4065          15 :         SetField(iField, 1, &dfValue);
    4066             :     }
    4067          23 :     else if (eType == OFTIntegerList)
    4068             :     {
    4069           1 :         int nValue = static_cast<int>(dfValue);
    4070           1 :         SetField(iField, 1, &nValue);
    4071             :     }
    4072          22 :     else if (eType == OFTInteger64List)
    4073             :     {
    4074           1 :         GIntBig nValue = static_cast<GIntBig>(dfValue);
    4075           1 :         SetField(iField, 1, &nValue);
    4076             :     }
    4077          21 :     else if (eType == OFTString)
    4078             :     {
    4079          16 :         char szTempBuffer[128] = {};
    4080             : 
    4081          16 :         CPLsnprintf(szTempBuffer, sizeof(szTempBuffer), "%.16g", dfValue);
    4082             : 
    4083          16 :         if (IsFieldSetAndNotNullUnsafe(iField))
    4084           7 :             CPLFree(pauFields[iField].String);
    4085             : 
    4086          16 :         pauFields[iField].String = VSI_STRDUP_VERBOSE(szTempBuffer);
    4087          16 :         if (pauFields[iField].String == nullptr)
    4088             :         {
    4089           0 :             OGR_RawField_SetUnset(&pauFields[iField]);
    4090             :         }
    4091             :     }
    4092           5 :     else if (eType == OFTStringList)
    4093             :     {
    4094           1 :         char szTempBuffer[64] = {};
    4095             : 
    4096           1 :         CPLsnprintf(szTempBuffer, sizeof(szTempBuffer), "%.16g", dfValue);
    4097           1 :         char *apszValues[2] = {szTempBuffer, nullptr};
    4098           1 :         SetField(iField, apszValues);
    4099             :     }
    4100             :     else
    4101             :     {
    4102             :         // Do nothing for other field types.
    4103             :     }
    4104             : }
    4105             : 
    4106             : /************************************************************************/
    4107             : /*                        OGR_F_SetFieldDouble()                        */
    4108             : /************************************************************************/
    4109             : 
    4110             : /**
    4111             :  * \brief Set field to double value.
    4112             :  *
    4113             :  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
    4114             :  * fields will be assigned a string representation of the value, but not
    4115             :  * necessarily taking into account formatting constraints on this field.  Other
    4116             :  * field types may be unaffected.
    4117             :  *
    4118             :  * This function is the same as the C++ method OGRFeature::SetField().
    4119             :  *
    4120             :  * @note This method has only an effect on the in-memory feature object. If
    4121             :  * this object comes from a layer and the modifications must be serialized back
    4122             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4123             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4124             :  *
    4125             :  * @param hFeat handle to the feature that owned the field.
    4126             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    4127             :  * @param dfValue the value to assign.
    4128             :  */
    4129             : 
    4130        2094 : void OGR_F_SetFieldDouble(OGRFeatureH hFeat, int iField, double dfValue)
    4131             : 
    4132             : {
    4133        2094 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDouble");
    4134             : 
    4135        2094 :     OGRFeature::FromHandle(hFeat)->SetField(iField, dfValue);
    4136             : }
    4137             : 
    4138             : /************************************************************************/
    4139             : /*                              SetField()                              */
    4140             : /************************************************************************/
    4141             : 
    4142             : /**
    4143             :  * \fn OGRFeature::SetField( const char* pszFName, const char * pszValue )
    4144             :  * \brief Set field to string value.
    4145             :  *
    4146             :  * OFTInteger fields will be set based on an atoi() conversion of the string.
    4147             :  * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the
    4148             :  * string.  OFTReal fields will be set based on an CPLAtof() conversion of the
    4149             :  * string.  Other field types may be unaffected.
    4150             :  *
    4151             :  * @note This method has only an effect on the in-memory feature object. If
    4152             :  * this object comes from a layer and the modifications must be serialized back
    4153             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4154             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4155             :  *
    4156             :  * @param pszFName the name of the field to set.
    4157             :  * @param pszValue the value to assign.
    4158             :  */
    4159             : 
    4160             : /**
    4161             :  * \brief Set field to string value.
    4162             :  *
    4163             :  * OFTInteger fields will be set based on an atoi() conversion of the string.
    4164             :  * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the
    4165             :  * string.  OFTReal fields will be set based on an CPLAtof() conversion of the
    4166             :  * string.  Other field types may be unaffected.
    4167             :  *
    4168             :  * This method is the same as the C function OGR_F_SetFieldString().
    4169             :  *
    4170             :  * @note This method has only an effect on the in-memory feature object. If
    4171             :  * this object comes from a layer and the modifications must be serialized back
    4172             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4173             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4174             :  *
    4175             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    4176             :  * @param pszValue the value to assign.
    4177             :  */
    4178             : 
    4179     2384030 : void OGRFeature::SetField(int iField, const char *pszValue)
    4180             : 
    4181             : {
    4182             :     static int bWarn = -1;
    4183     2384030 :     if (bWarn < 0)
    4184         396 :         bWarn = CPLTestBool(
    4185             :             CPLGetConfigOption("OGR_SETFIELD_NUMERIC_WARNING", "YES"));
    4186             : 
    4187     2384030 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    4188     2384030 :     if (poFDefn == nullptr)
    4189           1 :         return;
    4190             : 
    4191     2384030 :     char *pszLast = nullptr;
    4192             : 
    4193     2384030 :     OGRFieldType eType = poFDefn->GetType();
    4194     2384030 :     if (eType == OFTString)
    4195             :     {
    4196     2139360 :         if (IsFieldSetAndNotNullUnsafe(iField))
    4197        4445 :             CPLFree(pauFields[iField].String);
    4198             : 
    4199     2139360 :         pauFields[iField].String = VSI_STRDUP_VERBOSE(pszValue ? pszValue : "");
    4200     2139360 :         if (pauFields[iField].String == nullptr)
    4201             :         {
    4202           0 :             OGR_RawField_SetUnset(&pauFields[iField]);
    4203             :         }
    4204             :     }
    4205      244669 :     else if (eType == OFTInteger)
    4206             :     {
    4207       46009 :         if (poFDefn->GetSubType() == OFSTBoolean)
    4208             :         {
    4209         101 :             constexpr char DIGIT_ZERO = '0';
    4210         101 :             if ((pszValue[0] == '1' && pszValue[1] == '\0') ||
    4211          16 :                 EQUAL(pszValue, "true") || EQUAL(pszValue, "on") ||
    4212          12 :                 EQUAL(pszValue, "yes"))
    4213             :             {
    4214          90 :                 pauFields[iField].Integer = 1;
    4215          90 :                 pauFields[iField].Set.nMarker2 = 0;
    4216          90 :                 pauFields[iField].Set.nMarker3 = 0;
    4217             :             }
    4218          11 :             else if ((pszValue[0] == DIGIT_ZERO && pszValue[1] == '\0') ||
    4219           7 :                      EQUAL(pszValue, "false") || EQUAL(pszValue, "off") ||
    4220           4 :                      EQUAL(pszValue, "no"))
    4221             :             {
    4222           8 :                 pauFields[iField].Integer = 0;
    4223           8 :                 pauFields[iField].Set.nMarker2 = 0;
    4224           8 :                 pauFields[iField].Set.nMarker3 = 0;
    4225             :             }
    4226             :             else
    4227             :             {
    4228           3 :                 if (CPLGetValueType(pszValue) == CPL_VALUE_STRING)
    4229             :                 {
    4230           2 :                     CPLError(CE_Warning, CPLE_AppDefined,
    4231             :                              "Invalid value '%s' for boolean field %s.%s. "
    4232             :                              "Assuming it to be false.",
    4233           1 :                              pszValue, poDefn->GetName(),
    4234             :                              poFDefn->GetNameRef());
    4235           1 :                     pauFields[iField].Integer = 0;
    4236           1 :                     pauFields[iField].Set.nMarker2 = 0;
    4237           1 :                     pauFields[iField].Set.nMarker3 = 0;
    4238             :                 }
    4239             :                 else
    4240             :                 {
    4241           4 :                     CPLError(CE_Warning, CPLE_AppDefined,
    4242             :                              "Invalid value '%s' for boolean field %s.%s. "
    4243             :                              "Assuming it to be true.",
    4244           2 :                              pszValue, poDefn->GetName(),
    4245             :                              poFDefn->GetNameRef());
    4246           2 :                     pauFields[iField].Integer = 1;
    4247           2 :                     pauFields[iField].Set.nMarker2 = 0;
    4248           2 :                     pauFields[iField].Set.nMarker3 = 0;
    4249             :                 }
    4250             :             }
    4251             :         }
    4252             :         else
    4253             :         {
    4254             :             // As allowed by C standard, some systems like MSVC do not reset errno.
    4255       45908 :             errno = 0;
    4256             : 
    4257       45908 :             long long nVal64 = std::strtoll(pszValue, &pszLast, 10);
    4258       91801 :             int nVal32 = nVal64 > INT_MAX   ? INT_MAX
    4259       45893 :                          : nVal64 < INT_MIN ? INT_MIN
    4260             :                                             : static_cast<int>(nVal64);
    4261       91816 :             pauFields[iField].Integer =
    4262       45908 :                 OGRFeatureGetIntegerValue(poDefn, poFDefn, nVal32);
    4263       45908 :             if (bWarn && pauFields[iField].Integer == nVal32 &&
    4264       45908 :                 (errno == ERANGE || nVal32 != nVal64 || !pszLast || *pszLast))
    4265          21 :                 CPLError(CE_Warning, CPLE_AppDefined,
    4266             :                          "Value '%s' of field %s.%s parsed incompletely to "
    4267             :                          "integer %d.",
    4268          21 :                          pszValue, poDefn->GetName(), poFDefn->GetNameRef(),
    4269          21 :                          pauFields[iField].Integer);
    4270       45908 :             pauFields[iField].Set.nMarker2 = 0;
    4271       45908 :             pauFields[iField].Set.nMarker3 = 0;
    4272             :         }
    4273             :     }
    4274      198660 :     else if (eType == OFTInteger64)
    4275             :     {
    4276       93611 :         pauFields[iField].Integer64 = CPLAtoGIntBigEx(pszValue, bWarn, nullptr);
    4277       93611 :         pauFields[iField].Set.nMarker3 = 0;
    4278             :     }
    4279      105049 :     else if (eType == OFTReal)
    4280             :     {
    4281       92849 :         pauFields[iField].Real = CPLStrtod(pszValue, &pszLast);
    4282       92849 :         if (bWarn && (!pszLast || *pszLast))
    4283           1 :             CPLError(
    4284             :                 CE_Warning, CPLE_AppDefined,
    4285             :                 "Value '%s' of field %s.%s parsed incompletely to real %.16g.",
    4286           1 :                 pszValue, poDefn->GetName(), poFDefn->GetNameRef(),
    4287           1 :                 pauFields[iField].Real);
    4288             :     }
    4289       12200 :     else if (eType == OFTDate || eType == OFTTime || eType == OFTDateTime)
    4290             :     {
    4291             :         OGRField sWrkField;
    4292             : 
    4293       11507 :         if (OGRParseDate(pszValue, &sWrkField, 0))
    4294       11507 :             memcpy(pauFields + iField, &sWrkField, sizeof(sWrkField));
    4295             :     }
    4296         693 :     else if (eType == OFTIntegerList || eType == OFTInteger64List ||
    4297             :              eType == OFTRealList)
    4298             :     {
    4299         490 :         json_object *poJSonObj = nullptr;
    4300         614 :         if (pszValue[0] == '[' && pszValue[strlen(pszValue) - 1] == ']' &&
    4301         124 :             OGRJSonParse(pszValue, &poJSonObj, false))
    4302             :         {
    4303         124 :             const auto nLength = json_object_array_length(poJSonObj);
    4304         124 :             if (eType == OFTIntegerList && nLength > 0)
    4305             :             {
    4306         124 :                 std::vector<int> anValues;
    4307         193 :                 for (auto i = decltype(nLength){0}; i < nLength; i++)
    4308             :                 {
    4309             :                     json_object *poItem =
    4310         131 :                         json_object_array_get_idx(poJSonObj, i);
    4311         131 :                     anValues.push_back(json_object_get_int(poItem));
    4312             :                 }
    4313         124 :                 SetField(iField, static_cast<int>(nLength), &(anValues[0]));
    4314             :             }
    4315          62 :             else if (eType == OFTInteger64List && nLength > 0)
    4316             :             {
    4317          46 :                 std::vector<GIntBig> anValues;
    4318          70 :                 for (auto i = decltype(nLength){0}; i < nLength; i++)
    4319             :                 {
    4320             :                     json_object *poItem =
    4321          47 :                         json_object_array_get_idx(poJSonObj, i);
    4322          47 :                     anValues.push_back(json_object_get_int64(poItem));
    4323             :                 }
    4324          46 :                 SetField(iField, static_cast<int>(nLength), &(anValues[0]));
    4325             :             }
    4326          39 :             else if (eType == OFTRealList && nLength > 0)
    4327             :             {
    4328          78 :                 std::vector<double> adfValues;
    4329         120 :                 for (auto i = decltype(nLength){0}; i < nLength; i++)
    4330             :                 {
    4331             :                     json_object *poItem =
    4332          81 :                         json_object_array_get_idx(poJSonObj, i);
    4333          81 :                     adfValues.push_back(json_object_get_double(poItem));
    4334             :                 }
    4335          39 :                 SetField(iField, static_cast<int>(nLength), &(adfValues[0]));
    4336             :             }
    4337             : 
    4338         124 :             json_object_put(poJSonObj);
    4339             :         }
    4340             :         else
    4341             :         {
    4342         366 :             char **papszValueList = nullptr;
    4343             : 
    4344         366 :             if (pszValue[0] == '(' && strchr(pszValue, ':') != nullptr)
    4345             :             {
    4346         363 :                 papszValueList = CSLTokenizeString2(pszValue, ",:()", 0);
    4347             :             }
    4348             : 
    4349         729 :             if (papszValueList == nullptr || *papszValueList == nullptr ||
    4350         363 :                 atoi(papszValueList[0]) != CSLCount(papszValueList) - 1)
    4351             :             {
    4352             :                 // Do nothing - the count does not match entries.
    4353             :             }
    4354         363 :             else if (eType == OFTIntegerList)
    4355             :             {
    4356         131 :                 const int nCount = atoi(papszValueList[0]);
    4357         262 :                 std::vector<int> anValues;
    4358         131 :                 if (nCount == CSLCount(papszValueList) - 1)
    4359             :                 {
    4360         408 :                     for (int i = 0; i < nCount; i++)
    4361             :                     {
    4362             :                         // As allowed by C standard, some systems like
    4363             :                         // MSVC do not reset errno.
    4364         277 :                         errno = 0;
    4365         277 :                         int nVal = atoi(papszValueList[i + 1]);
    4366         277 :                         if (errno == ERANGE)
    4367             :                         {
    4368           0 :                             CPLError(
    4369             :                                 CE_Warning, CPLE_AppDefined,
    4370             :                                 "Field %s.%s: 32 bit integer overflow when "
    4371             :                                 "converting %s",
    4372           0 :                                 poDefn->GetName(), poFDefn->GetNameRef(),
    4373             :                                 pszValue);
    4374             :                         }
    4375         277 :                         anValues.push_back(nVal);
    4376             :                     }
    4377         131 :                     if (nCount > 0)
    4378         131 :                         SetField(iField, nCount, &(anValues[0]));
    4379             :                 }
    4380             :             }
    4381         232 :             else if (eType == OFTInteger64List)
    4382             :             {
    4383         116 :                 const int nCount = atoi(papszValueList[0]);
    4384         232 :                 std::vector<GIntBig> anValues;
    4385         116 :                 if (nCount == CSLCount(papszValueList) - 1)
    4386             :                 {
    4387         232 :                     for (int i = 0; i < nCount; i++)
    4388             :                     {
    4389         232 :                         const GIntBig nVal = CPLAtoGIntBigEx(
    4390         116 :                             papszValueList[i + 1], TRUE, nullptr);
    4391         116 :                         anValues.push_back(nVal);
    4392             :                     }
    4393         116 :                     if (nCount > 0)
    4394         116 :                         SetField(iField, nCount, &(anValues[0]));
    4395             :                 }
    4396             :             }
    4397         116 :             else if (eType == OFTRealList)
    4398             :             {
    4399         116 :                 int nCount = atoi(papszValueList[0]);
    4400         232 :                 std::vector<double> adfValues;
    4401         116 :                 if (nCount == CSLCount(papszValueList) - 1)
    4402             :                 {
    4403         232 :                     for (int i = 0; i < nCount; i++)
    4404         116 :                         adfValues.push_back(CPLAtof(papszValueList[i + 1]));
    4405         116 :                     if (nCount > 0)
    4406         116 :                         SetField(iField, nCount, &(adfValues[0]));
    4407             :                 }
    4408             :             }
    4409             : 
    4410         366 :             CSLDestroy(papszValueList);
    4411         490 :         }
    4412             :     }
    4413         203 :     else if (eType == OFTStringList)
    4414             :     {
    4415         202 :         if (pszValue && *pszValue)
    4416             :         {
    4417         202 :             json_object *poJSonObj = nullptr;
    4418         202 :             if (pszValue[0] == '(' && strchr(pszValue, ':') != nullptr &&
    4419         116 :                 pszValue[strlen(pszValue) - 1] == ')')
    4420             :             {
    4421         116 :                 char **papszValueList = CSLTokenizeString2(pszValue, ",:()", 0);
    4422         116 :                 const int nCount =
    4423         116 :                     papszValueList[0] == nullptr ? 0 : atoi(papszValueList[0]);
    4424         232 :                 std::vector<char *> aosValues;
    4425         116 :                 if (nCount == CSLCount(papszValueList) - 1)
    4426             :                 {
    4427         232 :                     for (int i = 0; i < nCount; i++)
    4428         116 :                         aosValues.push_back(papszValueList[i + 1]);
    4429         116 :                     aosValues.push_back(nullptr);
    4430         116 :                     SetField(iField, &(aosValues[0]));
    4431             :                 }
    4432         232 :                 CSLDestroy(papszValueList);
    4433             :             }
    4434             :             // Is this a JSon array?
    4435         226 :             else if (pszValue[0] == '[' &&
    4436         140 :                      pszValue[strlen(pszValue) - 1] == ']' &&
    4437          54 :                      OGRJSonParse(pszValue, &poJSonObj, false))
    4438             :             {
    4439         108 :                 CPLStringList aoList;
    4440          54 :                 const auto nLength = json_object_array_length(poJSonObj);
    4441         155 :                 for (auto i = decltype(nLength){0}; i < nLength; i++)
    4442             :                 {
    4443             :                     json_object *poItem =
    4444         101 :                         json_object_array_get_idx(poJSonObj, i);
    4445         101 :                     if (!poItem)
    4446           2 :                         aoList.AddString("");
    4447             :                     else
    4448          99 :                         aoList.AddString(json_object_get_string(poItem));
    4449             :                 }
    4450          54 :                 SetField(iField, aoList.List());
    4451          54 :                 json_object_put(poJSonObj);
    4452             :             }
    4453             :             else
    4454             :             {
    4455          32 :                 const char *const papszValues[2] = {pszValue, nullptr};
    4456          32 :                 SetField(iField, papszValues);
    4457             :             }
    4458             :         }
    4459             :     }
    4460             :     else
    4461             :     {
    4462             :         // Do nothing for other field types.
    4463             :     }
    4464             : }
    4465             : 
    4466             : /************************************************************************/
    4467             : /*                        OGR_F_SetFieldString()                        */
    4468             : /************************************************************************/
    4469             : 
    4470             : /**
    4471             :  * \brief Set field to string value.
    4472             :  *
    4473             :  * OFTInteger fields will be set based on an atoi() conversion of the string.
    4474             :  * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the
    4475             :  * string.  OFTReal fields will be set based on an CPLAtof() conversion of the
    4476             :  * string.  Other field types may be unaffected.
    4477             :  *
    4478             :  * This function is the same as the C++ method OGRFeature::SetField().
    4479             :  *
    4480             :  * @note This method has only an effect on the in-memory feature object. If
    4481             :  * this object comes from a layer and the modifications must be serialized back
    4482             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4483             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4484             :  *
    4485             :  * @param hFeat handle to the feature that owned the field.
    4486             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    4487             :  * @param pszValue the value to assign.
    4488             :  */
    4489             : 
    4490       12235 : void OGR_F_SetFieldString(OGRFeatureH hFeat, int iField, const char *pszValue)
    4491             : 
    4492             : {
    4493       12235 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldString");
    4494             : 
    4495       12235 :     OGRFeature::FromHandle(hFeat)->SetField(iField, pszValue);
    4496             : }
    4497             : 
    4498             : /************************************************************************/
    4499             : /*                              SetField()                              */
    4500             : /************************************************************************/
    4501             : 
    4502             : /**
    4503             :  * \fn OGRFeature::SetField( const char* pszFName, int nCount, const int
    4504             :  * *panValues ) \brief Set field to list of integers value.
    4505             :  *
    4506             :  * This method currently on has an effect of OFTIntegerList, OFTInteger64List
    4507             :  * and OFTRealList fields.
    4508             :  *
    4509             :  * @note This method has only an effect on the in-memory feature object. If
    4510             :  * this object comes from a layer and the modifications must be serialized back
    4511             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4512             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4513             :  *
    4514             :  * @param pszFName the name of the field to set.
    4515             :  * @param nCount the number of values in the list being assigned.
    4516             :  * @param panValues the values to assign.
    4517             :  */
    4518             : 
    4519             : /**
    4520             :  * \brief Set field to list of integers value.
    4521             :  *
    4522             :  * This method currently on has an effect of OFTIntegerList, OFTInteger64List
    4523             :  * and OFTRealList fields.
    4524             :  *
    4525             :  * This method is the same as the C function OGR_F_SetFieldIntegerList().
    4526             :  *
    4527             :  * @note This method has only an effect on the in-memory feature object. If
    4528             :  * this object comes from a layer and the modifications must be serialized back
    4529             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4530             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4531             :  *
    4532             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4533             :  * @param nCount the number of values in the list being assigned.
    4534             :  * @param panValues the values to assign.
    4535             :  */
    4536             : 
    4537       32519 : void OGRFeature::SetField(int iField, int nCount, const int *panValues)
    4538             : 
    4539             : {
    4540       32519 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    4541             : 
    4542       32519 :     if (poFDefn == nullptr)
    4543           0 :         return;
    4544             : 
    4545       32519 :     OGRFieldType eType = poFDefn->GetType();
    4546       32519 :     if (eType == OFTIntegerList)
    4547             :     {
    4548             :         OGRField uField;
    4549       32509 :         int *panValuesMod = nullptr;
    4550             : 
    4551       57765 :         if (poFDefn->GetSubType() == OFSTBoolean ||
    4552       25256 :             poFDefn->GetSubType() == OFSTInt16)
    4553             :         {
    4554       21612 :             for (int i = 0; i < nCount; i++)
    4555             :             {
    4556             :                 int nVal =
    4557       13937 :                     OGRFeatureGetIntegerValue(poDefn, poFDefn, panValues[i]);
    4558       13937 :                 if (panValues[i] != nVal)
    4559             :                 {
    4560           2 :                     if (panValuesMod == nullptr)
    4561             :                     {
    4562             :                         panValuesMod = static_cast<int *>(
    4563           2 :                             VSI_MALLOC_VERBOSE(nCount * sizeof(int)));
    4564           2 :                         if (panValuesMod == nullptr)
    4565           0 :                             return;
    4566           2 :                         if (nCount > 0)
    4567           2 :                             memcpy(panValuesMod, panValues,
    4568           2 :                                    nCount * sizeof(int));
    4569             :                     }
    4570           2 :                     panValuesMod[i] = nVal;
    4571             :                 }
    4572             :             }
    4573             :         }
    4574             : 
    4575       32509 :         uField.IntegerList.nCount = nCount;
    4576       32509 :         uField.Set.nMarker2 = 0;
    4577       32509 :         uField.Set.nMarker3 = 0;
    4578       32509 :         uField.IntegerList.paList =
    4579       32509 :             panValuesMod ? panValuesMod : const_cast<int *>(panValues);
    4580             : 
    4581       32509 :         SetField(iField, &uField);
    4582       32509 :         CPLFree(panValuesMod);
    4583             :     }
    4584          10 :     else if (eType == OFTInteger64List)
    4585             :     {
    4586           2 :         std::vector<GIntBig> anValues;
    4587           1 :         anValues.reserve(nCount);
    4588           4 :         for (int i = 0; i < nCount; i++)
    4589           3 :             anValues.push_back(panValues[i]);
    4590           1 :         if (nCount > 0)
    4591           1 :             SetField(iField, nCount, &anValues[0]);
    4592             :     }
    4593           9 :     else if (eType == OFTRealList)
    4594             :     {
    4595           2 :         std::vector<double> adfValues;
    4596           1 :         adfValues.reserve(nCount);
    4597           4 :         for (int i = 0; i < nCount; i++)
    4598           3 :             adfValues.push_back(static_cast<double>(panValues[i]));
    4599           1 :         if (nCount > 0)
    4600           1 :             SetField(iField, nCount, &adfValues[0]);
    4601             :     }
    4602           8 :     else if ((eType == OFTInteger || eType == OFTInteger64 ||
    4603           3 :               eType == OFTReal) &&
    4604             :              nCount == 1)
    4605             :     {
    4606           3 :         SetField(iField, panValues[0]);
    4607             :     }
    4608           5 :     else if (eType == OFTStringList)
    4609             :     {
    4610             :         char **papszValues = static_cast<char **>(
    4611           1 :             VSI_MALLOC_VERBOSE((nCount + 1) * sizeof(char *)));
    4612           1 :         if (papszValues == nullptr)
    4613           0 :             return;
    4614           4 :         for (int i = 0; i < nCount; i++)
    4615           3 :             papszValues[i] = VSI_STRDUP_VERBOSE(CPLSPrintf("%d", panValues[i]));
    4616           1 :         papszValues[nCount] = nullptr;
    4617           1 :         SetField(iField, papszValues);
    4618           1 :         CSLDestroy(papszValues);
    4619             :     }
    4620             : }
    4621             : 
    4622             : /************************************************************************/
    4623             : /*                     OGR_F_SetFieldIntegerList()                      */
    4624             : /************************************************************************/
    4625             : 
    4626             : /**
    4627             :  * \brief Set field to list of integers value.
    4628             :  *
    4629             :  * This function currently on has an effect of OFTIntegerList, OFTInteger64List
    4630             :  * and OFTRealList fields.
    4631             :  *
    4632             :  * This function is the same as the C++ method OGRFeature::SetField().
    4633             :  *
    4634             :  * @note This method has only an effect on the in-memory feature object. If
    4635             :  * this object comes from a layer and the modifications must be serialized back
    4636             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4637             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4638             :  *
    4639             :  * @param hFeat handle to the feature that owned the field.
    4640             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4641             :  * @param nCount the number of values in the list being assigned.
    4642             :  * @param panValues the values to assign.
    4643             :  */
    4644             : 
    4645           9 : void OGR_F_SetFieldIntegerList(OGRFeatureH hFeat, int iField, int nCount,
    4646             :                                const int *panValues)
    4647             : 
    4648             : {
    4649           9 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldIntegerList");
    4650             : 
    4651           9 :     OGRFeature::FromHandle(hFeat)->SetField(iField, nCount, panValues);
    4652             : }
    4653             : 
    4654             : /************************************************************************/
    4655             : /*                              SetField()                              */
    4656             : /************************************************************************/
    4657             : 
    4658             : /**
    4659             :  * \fn OGRFeature::SetField( const char* pszFName, int nCount, const GIntBig
    4660             :  * *panValues )
    4661             :  * \brief Set field to list of 64 bit integers value.
    4662             :  *
    4663             :  * This method currently on has an effect of OFTIntegerList, OFTInteger64List
    4664             :  * and OFTRealList fields.
    4665             :  *
    4666             :  * @note This method has only an effect on the in-memory feature object. If
    4667             :  * this object comes from a layer and the modifications must be serialized back
    4668             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4669             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4670             :  *
    4671             :  * @param pszFName the name of the field to set.
    4672             :  * @param nCount the number of values in the list being assigned.
    4673             :  * @param panValues the values to assign.
    4674             :  */
    4675             : 
    4676             : /**
    4677             :  * \brief Set field to list of 64 bit integers value.
    4678             :  *
    4679             :  * This method currently on has an effect of OFTIntegerList, OFTInteger64List
    4680             :  * and OFTRealList fields.
    4681             :  *
    4682             :  * This method is the same as the C function OGR_F_SetFieldInteger64List().
    4683             :  *
    4684             :  * @note This method has only an effect on the in-memory feature object. If
    4685             :  * this object comes from a layer and the modifications must be serialized back
    4686             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4687             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4688             :  *
    4689             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4690             :  * @param nCount the number of values in the list being assigned.
    4691             :  * @param panValues the values to assign.
    4692             :  */
    4693             : 
    4694       12831 : void OGRFeature::SetField(int iField, int nCount, const GIntBig *panValues)
    4695             : 
    4696             : {
    4697       12831 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    4698             : 
    4699       12831 :     if (poFDefn == nullptr)
    4700           0 :         return;
    4701             : 
    4702       12831 :     OGRFieldType eType = poFDefn->GetType();
    4703       12831 :     if (eType == OFTIntegerList)
    4704             :     {
    4705         150 :         std::vector<int> anValues;
    4706             : 
    4707         406 :         for (int i = 0; i < nCount; i++)
    4708             :         {
    4709         331 :             const GIntBig nValue = panValues[i];
    4710         662 :             const int nVal32 = nValue < INT_MIN   ? INT_MIN
    4711         331 :                                : nValue > INT_MAX ? INT_MAX
    4712             :                                                   : static_cast<int>(nValue);
    4713             : 
    4714         331 :             if (nVal32 != nValue)
    4715             :             {
    4716           2 :                 CPLError(
    4717             :                     CE_Warning, CPLE_AppDefined,
    4718             :                     "Field %s.%s: Integer overflow occurred when trying to "
    4719             :                     "set %" PRId64 " as 32 bit value.",
    4720           1 :                     poDefn->GetName(), poFDefn->GetNameRef(),
    4721             :                     static_cast<int64_t>(nValue));
    4722             :             }
    4723         331 :             anValues.push_back(nVal32);
    4724             :         }
    4725          75 :         if (nCount > 0)
    4726          75 :             SetField(iField, nCount, &anValues[0]);
    4727             :     }
    4728       12756 :     else if (eType == OFTInteger64List)
    4729             :     {
    4730             :         OGRField uField;
    4731       12746 :         uField.Integer64List.nCount = nCount;
    4732       12746 :         uField.Set.nMarker2 = 0;
    4733       12746 :         uField.Set.nMarker3 = 0;
    4734       12746 :         uField.Integer64List.paList = const_cast<GIntBig *>(panValues);
    4735             : 
    4736       12746 :         SetField(iField, &uField);
    4737             :     }
    4738          10 :     else if (eType == OFTRealList)
    4739             :     {
    4740           4 :         std::vector<double> adfValues;
    4741           2 :         adfValues.reserve(nCount);
    4742         103 :         for (int i = 0; i < nCount; i++)
    4743         101 :             adfValues.push_back(static_cast<double>(panValues[i]));
    4744           2 :         if (nCount > 0)
    4745           2 :             SetField(iField, nCount, &adfValues[0]);
    4746             :     }
    4747           8 :     else if ((eType == OFTInteger || eType == OFTInteger64 ||
    4748           3 :               eType == OFTReal) &&
    4749             :              nCount == 1)
    4750             :     {
    4751           3 :         SetField(iField, panValues[0]);
    4752             :     }
    4753           5 :     else if (eType == OFTStringList)
    4754             :     {
    4755             :         char **papszValues = static_cast<char **>(
    4756           1 :             VSI_MALLOC_VERBOSE((nCount + 1) * sizeof(char *)));
    4757           1 :         if (papszValues == nullptr)
    4758           0 :             return;
    4759           2 :         for (int i = 0; i < nCount; i++)
    4760           2 :             papszValues[i] =
    4761           1 :                 VSI_STRDUP_VERBOSE(CPLSPrintf(CPL_FRMT_GIB, panValues[i]));
    4762           1 :         papszValues[nCount] = nullptr;
    4763           1 :         SetField(iField, papszValues);
    4764           1 :         CSLDestroy(papszValues);
    4765             :     }
    4766             : }
    4767             : 
    4768             : /************************************************************************/
    4769             : /*                    OGR_F_SetFieldInteger64List()                     */
    4770             : /************************************************************************/
    4771             : 
    4772             : /**
    4773             :  * \brief Set field to list of 64 bit integers value.
    4774             :  *
    4775             :  * This function currently on has an effect of OFTIntegerList, OFTInteger64List
    4776             :  * and OFTRealList fields.
    4777             :  *
    4778             :  * This function is the same as the C++ method OGRFeature::SetField().
    4779             :  *
    4780             :  * @note This method has only an effect on the in-memory feature object. If
    4781             :  * this object comes from a layer and the modifications must be serialized back
    4782             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4783             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4784             :  *
    4785             :  * @param hFeat handle to the feature that owned the field.
    4786             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4787             :  * @param nCount the number of values in the list being assigned.
    4788             :  * @param panValues the values to assign.
    4789             :  */
    4790             : 
    4791         124 : void OGR_F_SetFieldInteger64List(OGRFeatureH hFeat, int iField, int nCount,
    4792             :                                  const GIntBig *panValues)
    4793             : 
    4794             : {
    4795         124 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldInteger64List");
    4796             : 
    4797         124 :     OGRFeature::FromHandle(hFeat)->SetField(iField, nCount, panValues);
    4798             : }
    4799             : 
    4800             : /************************************************************************/
    4801             : /*                              SetField()                              */
    4802             : /************************************************************************/
    4803             : 
    4804             : /**
    4805             :  * \fn OGRFeature::SetField( const char* pszFName, int nCount, const double *
    4806             :  * padfValues ) \brief Set field to list of doubles value.
    4807             :  *
    4808             :  * This method currently on has an effect of OFTIntegerList, OFTInteger64List,
    4809             :  * OFTRealList fields.
    4810             :  *
    4811             :  * @note This method has only an effect on the in-memory feature object. If
    4812             :  * this object comes from a layer and the modifications must be serialized back
    4813             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4814             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4815             :  *
    4816             :  * @param pszFName the name of the field to set.
    4817             :  * @param nCount the number of values in the list being assigned.
    4818             :  * @param padfValues the values to assign.
    4819             :  */
    4820             : 
    4821             : /**
    4822             :  * \brief Set field to list of doubles value.
    4823             :  *
    4824             :  * This method currently on has an effect of OFTIntegerList, OFTInteger64List,
    4825             :  * OFTRealList fields.
    4826             :  *
    4827             :  * This method is the same as the C function OGR_F_SetFieldDoubleList().
    4828             :  *
    4829             :  * @note This method has only an effect on the in-memory feature object. If
    4830             :  * this object comes from a layer and the modifications must be serialized back
    4831             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4832             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4833             :  *
    4834             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4835             :  * @param nCount the number of values in the list being assigned.
    4836             :  * @param padfValues the values to assign.
    4837             :  */
    4838             : 
    4839       21054 : void OGRFeature::SetField(int iField, int nCount, const double *padfValues)
    4840             : 
    4841             : {
    4842       21054 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    4843             : 
    4844       21054 :     if (poFDefn == nullptr)
    4845           0 :         return;
    4846             : 
    4847       21054 :     OGRFieldType eType = poFDefn->GetType();
    4848       21054 :     if (eType == OFTRealList)
    4849             :     {
    4850             :         OGRField uField;
    4851             : 
    4852       20797 :         uField.RealList.nCount = nCount;
    4853       20797 :         uField.Set.nMarker2 = 0;
    4854       20797 :         uField.Set.nMarker3 = 0;
    4855       20797 :         uField.RealList.paList = const_cast<double *>(padfValues);
    4856             : 
    4857       20797 :         SetField(iField, &uField);
    4858             :     }
    4859         257 :     else if (eType == OFTIntegerList)
    4860             :     {
    4861         366 :         std::vector<int> anValues;
    4862         183 :         anValues.reserve(nCount);
    4863         507 :         for (int i = 0; i < nCount; i++)
    4864         324 :             anValues.push_back(static_cast<int>(padfValues[i]));
    4865             : 
    4866         183 :         if (nCount > 0)
    4867         183 :             SetField(iField, nCount, &anValues[0]);
    4868             :     }
    4869          74 :     else if (eType == OFTInteger64List)
    4870             :     {
    4871           4 :         std::vector<GIntBig> anValues;
    4872           2 :         anValues.reserve(nCount);
    4873           5 :         for (int i = 0; i < nCount; i++)
    4874           3 :             anValues.push_back(static_cast<GIntBig>(padfValues[i]));
    4875           2 :         if (nCount > 0)
    4876           2 :             SetField(iField, nCount, &anValues[0]);
    4877             :     }
    4878          72 :     else if ((eType == OFTInteger || eType == OFTInteger64 ||
    4879          67 :               eType == OFTReal) &&
    4880             :              nCount == 1)
    4881             :     {
    4882          67 :         SetField(iField, padfValues[0]);
    4883             :     }
    4884           5 :     else if (eType == OFTStringList)
    4885             :     {
    4886             :         char **papszValues = static_cast<char **>(
    4887           1 :             VSI_MALLOC_VERBOSE((nCount + 1) * sizeof(char *)));
    4888           1 :         if (papszValues == nullptr)
    4889           0 :             return;
    4890           3 :         for (int i = 0; i < nCount; i++)
    4891           4 :             papszValues[i] =
    4892           2 :                 VSI_STRDUP_VERBOSE(CPLSPrintf("%.16g", padfValues[i]));
    4893           1 :         papszValues[nCount] = nullptr;
    4894           1 :         SetField(iField, papszValues);
    4895           1 :         CSLDestroy(papszValues);
    4896             :     }
    4897             : }
    4898             : 
    4899             : /************************************************************************/
    4900             : /*                      OGR_F_SetFieldDoubleList()                      */
    4901             : /************************************************************************/
    4902             : 
    4903             : /**
    4904             :  * \brief Set field to list of doubles value.
    4905             :  *
    4906             :  * This function currently on has an effect of OFTIntegerList, OFTInteger64List,
    4907             :  * OFTRealList fields.
    4908             :  *
    4909             :  * This function is the same as the C++ method OGRFeature::SetField().
    4910             :  *
    4911             :  * @note This method has only an effect on the in-memory feature object. If
    4912             :  * this object comes from a layer and the modifications must be serialized back
    4913             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4914             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4915             :  *
    4916             :  * @param hFeat handle to the feature that owned the field.
    4917             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4918             :  * @param nCount the number of values in the list being assigned.
    4919             :  * @param padfValues the values to assign.
    4920             :  */
    4921             : 
    4922          91 : void OGR_F_SetFieldDoubleList(OGRFeatureH hFeat, int iField, int nCount,
    4923             :                               const double *padfValues)
    4924             : 
    4925             : {
    4926          91 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDoubleList");
    4927             : 
    4928          91 :     OGRFeature::FromHandle(hFeat)->SetField(iField, nCount, padfValues);
    4929             : }
    4930             : 
    4931             : /************************************************************************/
    4932             : /*                              SetField()                              */
    4933             : /************************************************************************/
    4934             : 
    4935             : /**
    4936             :  * \fn OGRFeature::SetField( const char* pszFName,  const char * const *
    4937             :  * papszValues ) \brief Set field to list of strings value.
    4938             :  *
    4939             :  * This method currently on has an effect of OFTStringList fields.
    4940             :  *
    4941             :  * @note This method has only an effect on the in-memory feature object. If
    4942             :  * this object comes from a layer and the modifications must be serialized back
    4943             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4944             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4945             :  *
    4946             :  * @param pszFName the name of the field to set.
    4947             :  * @param papszValues the values to assign. List of NUL-terminated string,
    4948             :  * ending with a NULL pointer.
    4949             :  */
    4950             : 
    4951             : /**
    4952             :  * \brief Set field to list of strings value.
    4953             :  *
    4954             :  * This method currently on has an effect of OFTStringList fields.
    4955             :  *
    4956             :  * This method is the same as the C function OGR_F_SetFieldStringList().
    4957             :  *
    4958             :  * @note This method has only an effect on the in-memory feature object. If
    4959             :  * this object comes from a layer and the modifications must be serialized back
    4960             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4961             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4962             :  *
    4963             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4964             :  * @param papszValues the values to assign. List of NUL-terminated string,
    4965             :  * ending with a NULL pointer.
    4966             :  */
    4967             : 
    4968       37763 : void OGRFeature::SetField(int iField, const char *const *papszValues)
    4969             : 
    4970             : {
    4971       37763 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    4972             : 
    4973       37763 :     if (poFDefn == nullptr)
    4974           0 :         return;
    4975             : 
    4976       37763 :     OGRFieldType eType = poFDefn->GetType();
    4977       37763 :     if (eType == OFTStringList)
    4978             :     {
    4979       24527 :         if (!IsFieldSetAndNotNullUnsafe(iField) ||
    4980        5629 :             papszValues != pauFields[iField].StringList.paList)
    4981             :         {
    4982             :             OGRField uField;
    4983             : 
    4984       18896 :             uField.StringList.nCount = CSLCount(papszValues);
    4985       18896 :             uField.Set.nMarker2 = 0;
    4986       18896 :             uField.Set.nMarker3 = 0;
    4987       18896 :             uField.StringList.paList = const_cast<char **>(papszValues);
    4988             : 
    4989       18896 :             SetField(iField, &uField);
    4990             :         }
    4991             :     }
    4992       18865 :     else if (eType == OFTIntegerList)
    4993             :     {
    4994        9845 :         const int nValues = CSLCount(papszValues);
    4995             :         int *panValues =
    4996        9845 :             static_cast<int *>(VSI_MALLOC_VERBOSE(nValues * sizeof(int)));
    4997        9845 :         if (panValues == nullptr)
    4998           0 :             return;
    4999       28447 :         for (int i = 0; i < nValues; i++)
    5000             :         {
    5001             :             // As allowed by C standard, some systems like MSVC do not
    5002             :             // reset errno.
    5003       18602 :             errno = 0;
    5004             : 
    5005       18602 :             int nVal = atoi(papszValues[i]);
    5006       18602 :             if (errno == ERANGE)
    5007             :             {
    5008           0 :                 CPLError(
    5009             :                     CE_Warning, CPLE_AppDefined,
    5010             :                     "Field %s.%s: 32 bit integer overflow when converting %s",
    5011           0 :                     poDefn->GetName(), poFDefn->GetNameRef(), papszValues[i]);
    5012           0 :                 if (papszValues[i][0] == '-')
    5013           0 :                     nVal = INT_MIN;
    5014             :                 else
    5015           0 :                     nVal = INT_MAX;
    5016             :             }
    5017       18602 :             panValues[i] = nVal;
    5018             :         }
    5019        9845 :         SetField(iField, nValues, panValues);
    5020        9845 :         CPLFree(panValues);
    5021             :     }
    5022        9020 :     else if (eType == OFTInteger64List)
    5023             :     {
    5024        3377 :         const int nValues = CSLCount(papszValues);
    5025             :         GIntBig *panValues = static_cast<GIntBig *>(
    5026        3377 :             VSI_MALLOC_VERBOSE(nValues * sizeof(GIntBig)));
    5027        3377 :         if (panValues == nullptr)
    5028           0 :             return;
    5029       10073 :         for (int i = 0; i < nValues; i++)
    5030             :         {
    5031        6696 :             panValues[i] = CPLAtoGIntBigEx(papszValues[i], TRUE, nullptr);
    5032             :         }
    5033        3377 :         SetField(iField, nValues, panValues);
    5034        3377 :         CPLFree(panValues);
    5035             :     }
    5036        5643 :     else if (eType == OFTRealList)
    5037             :     {
    5038        5643 :         const int nValues = CSLCount(papszValues);
    5039             :         double *padfValues =
    5040        5643 :             static_cast<double *>(VSI_MALLOC_VERBOSE(nValues * sizeof(double)));
    5041        5643 :         if (padfValues == nullptr)
    5042           0 :             return;
    5043       15738 :         for (int i = 0; i < nValues; i++)
    5044             :         {
    5045       10095 :             padfValues[i] = CPLAtof(papszValues[i]);
    5046             :         }
    5047        5643 :         SetField(iField, nValues, padfValues);
    5048        5643 :         CPLFree(padfValues);
    5049             :     }
    5050             : }
    5051             : 
    5052             : /************************************************************************/
    5053             : /*                      OGR_F_SetFieldStringList()                      */
    5054             : /************************************************************************/
    5055             : 
    5056             : /**
    5057             :  * \brief Set field to list of strings value.
    5058             :  *
    5059             :  * This function currently on has an effect of OFTStringList fields.
    5060             :  *
    5061             :  * This function is the same as the C++ method OGRFeature::SetField().
    5062             :  *
    5063             :  * @note This method has only an effect on the in-memory feature object. If
    5064             :  * this object comes from a layer and the modifications must be serialized back
    5065             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5066             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5067             :  *
    5068             :  * @param hFeat handle to the feature that owned the field.
    5069             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    5070             :  * @param papszValues the values to assign. List of NUL-terminated string,
    5071             :  * ending with a NULL pointer.
    5072             :  */
    5073             : 
    5074          43 : void OGR_F_SetFieldStringList(OGRFeatureH hFeat, int iField,
    5075             :                               CSLConstList papszValues)
    5076             : 
    5077             : {
    5078          43 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldStringList");
    5079             : 
    5080          43 :     OGRFeature::FromHandle(hFeat)->SetField(iField, papszValues);
    5081             : }
    5082             : 
    5083             : /************************************************************************/
    5084             : /*                              SetField()                              */
    5085             : /************************************************************************/
    5086             : 
    5087             : /**
    5088             :  * \brief Set field to binary data.
    5089             :  *
    5090             :  * This method currently on has an effect of OFTBinary fields.
    5091             :  *
    5092             :  * This method is the same as the C function OGR_F_SetFieldBinary().
    5093             :  *
    5094             :  * @note This method has only an effect on the in-memory feature object. If
    5095             :  * this object comes from a layer and the modifications must be serialized back
    5096             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5097             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5098             :  *
    5099             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    5100             :  * @param nBytes bytes of data being set.
    5101             :  * @param pabyData the raw data being applied.
    5102             :  */
    5103             : 
    5104       17976 : void OGRFeature::SetField(int iField, int nBytes, const void *pabyData)
    5105             : 
    5106             : {
    5107       17976 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    5108             : 
    5109       17976 :     if (poFDefn == nullptr)
    5110           0 :         return;
    5111             : 
    5112       17976 :     OGRFieldType eType = poFDefn->GetType();
    5113       17976 :     if (eType == OFTBinary)
    5114             :     {
    5115             :         OGRField uField;
    5116             : 
    5117       17973 :         uField.Binary.nCount = nBytes;
    5118       17973 :         uField.Set.nMarker2 = 0;
    5119       17973 :         uField.Set.nMarker3 = 0;
    5120       17973 :         uField.Binary.paData =
    5121             :             const_cast<GByte *>(static_cast<const GByte *>(pabyData));
    5122             : 
    5123       17973 :         SetField(iField, &uField);
    5124             :     }
    5125           3 :     else if (eType == OFTString || eType == OFTStringList)
    5126             :     {
    5127           3 :         char *pszStr = static_cast<char *>(VSI_MALLOC_VERBOSE(nBytes + 1));
    5128           3 :         if (pszStr == nullptr)
    5129           0 :             return;
    5130           3 :         if (nBytes > 0)
    5131           3 :             memcpy(pszStr, pabyData, nBytes);
    5132           3 :         pszStr[nBytes] = 0;
    5133           3 :         SetField(iField, pszStr);
    5134           3 :         CPLFree(pszStr);
    5135             :     }
    5136             : }
    5137             : 
    5138             : /************************************************************************/
    5139             : /*                        OGR_F_SetFieldBinary()                        */
    5140             : /************************************************************************/
    5141             : 
    5142             : /**
    5143             :  * \brief Set field to binary data.
    5144             :  *
    5145             :  * This function currently on has an effect of OFTBinary fields.
    5146             :  *
    5147             :  * This function is the same as the C++ method OGRFeature::SetField().
    5148             :  *
    5149             :  * @note This method has only an effect on the in-memory feature object. If
    5150             :  * this object comes from a layer and the modifications must be serialized back
    5151             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5152             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5153             :  *
    5154             :  * @param hFeat handle to the feature that owned the field.
    5155             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    5156             :  * @param nBytes the number of bytes in pabyData array.
    5157             :  * @param pabyData the data to apply.
    5158             :  */
    5159             : 
    5160         524 : void OGR_F_SetFieldBinary(OGRFeatureH hFeat, int iField, int nBytes,
    5161             :                           const void *pabyData)
    5162             : 
    5163             : {
    5164         524 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldBinary");
    5165             : 
    5166         524 :     OGRFeature::FromHandle(hFeat)->SetField(iField, nBytes, pabyData);
    5167             : }
    5168             : 
    5169             : /************************************************************************/
    5170             : /*                              SetField()                              */
    5171             : /************************************************************************/
    5172             : 
    5173             : /**
    5174             :  * \fn OGRFeature::SetField( const char* pszFName, int nYear, int nMonth,
    5175             :  *                           int nDay, int nHour, int nMinute, float fSecond,
    5176             :  *                           int nTZFlag )
    5177             :  * \brief Set field to date.
    5178             :  *
    5179             :  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
    5180             :  * fields.
    5181             :  *
    5182             :  * @note This method has only an effect on the in-memory feature object. If
    5183             :  * this object comes from a layer and the modifications must be serialized back
    5184             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5185             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5186             :  *
    5187             :  * @param pszFName the name of the field to set.
    5188             :  * @param nYear (including century)
    5189             :  * @param nMonth (1-12)
    5190             :  * @param nDay (1-31)
    5191             :  * @param nHour (0-23)
    5192             :  * @param nMinute (0-59)
    5193             :  * @param fSecond (0-59, with millisecond accuracy)
    5194             :  * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
    5195             :  */
    5196             : 
    5197             : /**
    5198             :  * \brief Set field to date.
    5199             :  *
    5200             :  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
    5201             :  * fields.
    5202             :  *
    5203             :  * This method is the same as the C function OGR_F_SetFieldDateTime().
    5204             :  *
    5205             :  * @note This method has only an effect on the in-memory feature object. If
    5206             :  * this object comes from a layer and the modifications must be serialized back
    5207             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5208             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5209             :  *
    5210             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    5211             :  * @param nYear (including century)
    5212             :  * @param nMonth (1-12)
    5213             :  * @param nDay (1-31)
    5214             :  * @param nHour (0-23)
    5215             :  * @param nMinute (0-59)
    5216             :  * @param fSecond (0-59, with millisecond accuracy)
    5217             :  * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
    5218             :  */
    5219             : 
    5220       10655 : void OGRFeature::SetField(int iField, int nYear, int nMonth, int nDay,
    5221             :                           int nHour, int nMinute, float fSecond, int nTZFlag)
    5222             : 
    5223             : {
    5224       10655 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    5225             : 
    5226       10655 :     if (poFDefn == nullptr)
    5227           0 :         return;
    5228             : 
    5229       10655 :     OGRFieldType eType = poFDefn->GetType();
    5230       10655 :     if (eType == OFTDate || eType == OFTTime || eType == OFTDateTime)
    5231             :     {
    5232       10647 :         if (static_cast<GInt16>(nYear) != nYear)
    5233             :         {
    5234           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    5235             :                      "Years < -32768 or > 32767 are not supported");
    5236           0 :             return;
    5237             :         }
    5238             : 
    5239       10647 :         pauFields[iField].Date.Year = static_cast<GInt16>(nYear);
    5240       10647 :         pauFields[iField].Date.Month = static_cast<GByte>(nMonth);
    5241       10647 :         pauFields[iField].Date.Day = static_cast<GByte>(nDay);
    5242       10647 :         pauFields[iField].Date.Hour = static_cast<GByte>(nHour);
    5243       10647 :         pauFields[iField].Date.Minute = static_cast<GByte>(nMinute);
    5244       10647 :         pauFields[iField].Date.Second = fSecond;
    5245       10647 :         pauFields[iField].Date.TZFlag = static_cast<GByte>(nTZFlag);
    5246             :     }
    5247           8 :     else if (eType == OFTString || eType == OFTStringList)
    5248             :     {
    5249             :         // "YYYY/MM/DD HH:MM:SS.sss+ZZ"
    5250           8 :         constexpr size_t MAX_SIZE = 26 + 1;
    5251           8 :         char szTempBuffer[MAX_SIZE] = {};
    5252           8 :         OGRFeatureFormatDateTimeBuffer(szTempBuffer, MAX_SIZE, nYear, nMonth,
    5253             :                                        nDay, nHour, nMinute, fSecond, nTZFlag);
    5254           8 :         SetField(iField, szTempBuffer);
    5255             :     }
    5256             : }
    5257             : 
    5258             : /************************************************************************/
    5259             : /*                       OGR_F_SetFieldDateTime()                       */
    5260             : /************************************************************************/
    5261             : 
    5262             : /**
    5263             :  * \brief Set field to datetime.
    5264             :  *
    5265             :  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
    5266             :  * fields.
    5267             :  *
    5268             :  * @note This method has only an effect on the in-memory feature object. If
    5269             :  * this object comes from a layer and the modifications must be serialized back
    5270             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5271             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5272             :  *
    5273             :  * @param hFeat handle to the feature that owned the field.
    5274             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    5275             :  * @param nYear (including century)
    5276             :  * @param nMonth (1-12)
    5277             :  * @param nDay (1-31)
    5278             :  * @param nHour (0-23)
    5279             :  * @param nMinute (0-59)
    5280             :  * @param nSecond (0-59)
    5281             :  * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
    5282             :  *
    5283             :  * @see Use OGR_F_SetFieldDateTimeEx() for second with millisecond accuracy.
    5284             :  */
    5285             : 
    5286           0 : void OGR_F_SetFieldDateTime(OGRFeatureH hFeat, int iField, int nYear,
    5287             :                             int nMonth, int nDay, int nHour, int nMinute,
    5288             :                             int nSecond, int nTZFlag)
    5289             : 
    5290             : {
    5291           0 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDateTime");
    5292             : 
    5293           0 :     OGRFeature::FromHandle(hFeat)->SetField(
    5294             :         iField, nYear, nMonth, nDay, nHour, nMinute,
    5295             :         static_cast<float>(nSecond), nTZFlag);
    5296             : }
    5297             : 
    5298             : /************************************************************************/
    5299             : /*                      OGR_F_SetFieldDateTimeEx()                      */
    5300             : /************************************************************************/
    5301             : 
    5302             : /**
    5303             :  * \brief Set field to datetime.
    5304             :  *
    5305             :  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
    5306             :  * fields.
    5307             :  *
    5308             :  * @note This method has only an effect on the in-memory feature object. If
    5309             :  * this object comes from a layer and the modifications must be serialized back
    5310             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5311             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5312             :  *
    5313             :  * @param hFeat handle to the feature that owned the field.
    5314             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    5315             :  * @param nYear (including century)
    5316             :  * @param nMonth (1-12)
    5317             :  * @param nDay (1-31)
    5318             :  * @param nHour (0-23)
    5319             :  * @param nMinute (0-59)
    5320             :  * @param fSecond (0-59, with millisecond accuracy)
    5321             :  * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
    5322             :  *
    5323             :  */
    5324             : 
    5325          45 : void OGR_F_SetFieldDateTimeEx(OGRFeatureH hFeat, int iField, int nYear,
    5326             :                               int nMonth, int nDay, int nHour, int nMinute,
    5327             :                               float fSecond, int nTZFlag)
    5328             : 
    5329             : {
    5330          45 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDateTimeEx");
    5331             : 
    5332          45 :     OGRFeature::FromHandle(hFeat)->SetField(iField, nYear, nMonth, nDay, nHour,
    5333             :                                             nMinute, fSecond, nTZFlag);
    5334             : }
    5335             : 
    5336             : /************************************************************************/
    5337             : /*                              SetField()                              */
    5338             : /************************************************************************/
    5339             : 
    5340             : /**
    5341             :  * \fn OGRFeature::SetField( const char* pszFName, const OGRField * puValue )
    5342             :  * \brief Set field.
    5343             :  *
    5344             :  * The passed value OGRField must be of exactly the same type as the
    5345             :  * target field, or an application crash may occur.  The passed value
    5346             :  * is copied, and will not be affected.  It remains the responsibility of
    5347             :  * the caller.
    5348             :  *
    5349             :  * @note This method has only an effect on the in-memory feature object. If
    5350             :  * this object comes from a layer and the modifications must be serialized back
    5351             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5352             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5353             :  *
    5354             :  * @param pszFName the name of the field to set.
    5355             :  * @param puValue the value to assign.
    5356             :  */
    5357             : 
    5358             : /**
    5359             :  * \brief Set field.
    5360             :  *
    5361             :  * The passed value OGRField must be of exactly the same type as the
    5362             :  * target field, or an application crash may occur.  The passed value
    5363             :  * is copied, and will not be affected.  It remains the responsibility of
    5364             :  * the caller.
    5365             :  *
    5366             :  * This method is the same as the C function OGR_F_SetFieldRaw().
    5367             :  *
    5368             :  * @note This method has only an effect on the in-memory feature object. If
    5369             :  * this object comes from a layer and the modifications must be serialized back
    5370             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5371             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5372             :  *
    5373             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    5374             :  * @param puValue the value to assign.
    5375             :  */
    5376             : 
    5377      389901 : void OGRFeature::SetField(int iField, const OGRField *puValue)
    5378             : 
    5379             : {
    5380      389901 :     SetFieldInternal(iField, puValue);
    5381      389901 : }
    5382             : 
    5383     4619710 : bool OGRFeature::SetFieldInternal(int iField, const OGRField *puValue)
    5384             : 
    5385             : {
    5386     4619710 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    5387     4619710 :     if (iField < 0 || poFDefn == nullptr)
    5388           0 :         return false;
    5389             : 
    5390     4619710 :     if (poFDefn->GetType() == OFTInteger)
    5391             :     {
    5392     1313480 :         pauFields[iField] = *puValue;
    5393             :     }
    5394     3306230 :     else if (poFDefn->GetType() == OFTInteger64)
    5395             :     {
    5396       25300 :         pauFields[iField] = *puValue;
    5397             :     }
    5398     3280930 :     else if (poFDefn->GetType() == OFTReal)
    5399             :     {
    5400       76188 :         pauFields[iField] = *puValue;
    5401             :     }
    5402     3204750 :     else if (poFDefn->GetType() == OFTString)
    5403             :     {
    5404     2911620 :         if (IsFieldSetAndNotNullUnsafe(iField))
    5405          28 :             CPLFree(pauFields[iField].String);
    5406             : 
    5407     2911620 :         if (puValue->String == nullptr)
    5408           0 :             pauFields[iField].String = nullptr;
    5409     2911620 :         else if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
    5410     1218320 :             pauFields[iField] = *puValue;
    5411             :         else
    5412             :         {
    5413     1693300 :             pauFields[iField].String = VSI_STRDUP_VERBOSE(puValue->String);
    5414     1693300 :             if (pauFields[iField].String == nullptr)
    5415             :             {
    5416           0 :                 OGR_RawField_SetUnset(&pauFields[iField]);
    5417           0 :                 return false;
    5418             :             }
    5419             :         }
    5420             :     }
    5421      541726 :     else if (poFDefn->GetType() == OFTDate || poFDefn->GetType() == OFTTime ||
    5422      248601 :              poFDefn->GetType() == OFTDateTime)
    5423             :     {
    5424      105569 :         memcpy(pauFields + iField, puValue, sizeof(OGRField));
    5425             :     }
    5426      187556 :     else if (poFDefn->GetType() == OFTIntegerList)
    5427             :     {
    5428       43769 :         const int nCount = puValue->IntegerList.nCount;
    5429             : 
    5430       43769 :         if (IsFieldSetAndNotNullUnsafe(iField))
    5431        3343 :             CPLFree(pauFields[iField].IntegerList.paList);
    5432             : 
    5433       43769 :         if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
    5434             :         {
    5435         350 :             pauFields[iField] = *puValue;
    5436             :         }
    5437             :         else
    5438             :         {
    5439       86838 :             pauFields[iField].IntegerList.paList =
    5440       43419 :                 static_cast<int *>(VSI_MALLOC_VERBOSE(sizeof(int) * nCount));
    5441       43419 :             if (pauFields[iField].IntegerList.paList == nullptr)
    5442             :             {
    5443           0 :                 OGR_RawField_SetUnset(&pauFields[iField]);
    5444           0 :                 return false;
    5445             :             }
    5446       43419 :             if (nCount > 0)
    5447             :             {
    5448       40417 :                 memcpy(pauFields[iField].IntegerList.paList,
    5449       40417 :                        puValue->IntegerList.paList, sizeof(int) * nCount);
    5450             :             }
    5451       43419 :             pauFields[iField].IntegerList.nCount = nCount;
    5452             :         }
    5453             :     }
    5454      143787 :     else if (poFDefn->GetType() == OFTInteger64List)
    5455             :     {
    5456       23299 :         const int nCount = puValue->Integer64List.nCount;
    5457             : 
    5458       23299 :         if (IsFieldSetAndNotNullUnsafe(iField))
    5459        1168 :             CPLFree(pauFields[iField].Integer64List.paList);
    5460             : 
    5461       23299 :         if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
    5462             :         {
    5463         111 :             pauFields[iField] = *puValue;
    5464             :         }
    5465             :         else
    5466             :         {
    5467       46376 :             pauFields[iField].Integer64List.paList = static_cast<GIntBig *>(
    5468       23188 :                 VSI_MALLOC_VERBOSE(sizeof(GIntBig) * nCount));
    5469       23188 :             if (pauFields[iField].Integer64List.paList == nullptr)
    5470             :             {
    5471           0 :                 OGR_RawField_SetUnset(&pauFields[iField]);
    5472           0 :                 return false;
    5473             :             }
    5474       23188 :             if (nCount > 0)
    5475             :             {
    5476       22227 :                 memcpy(pauFields[iField].Integer64List.paList,
    5477       22227 :                        puValue->Integer64List.paList, sizeof(GIntBig) * nCount);
    5478             :             }
    5479       23188 :             pauFields[iField].Integer64List.nCount = nCount;
    5480             :         }
    5481             :     }
    5482      120488 :     else if (poFDefn->GetType() == OFTRealList)
    5483             :     {
    5484       31975 :         const int nCount = puValue->RealList.nCount;
    5485             : 
    5486       31975 :         if (IsFieldSetAndNotNullUnsafe(iField))
    5487        2343 :             CPLFree(pauFields[iField].RealList.paList);
    5488             : 
    5489       31975 :         if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
    5490             :         {
    5491       10412 :             pauFields[iField] = *puValue;
    5492             :         }
    5493             :         else
    5494             :         {
    5495       43126 :             pauFields[iField].RealList.paList = static_cast<double *>(
    5496       21563 :                 VSI_MALLOC_VERBOSE(sizeof(double) * nCount));
    5497       21563 :             if (pauFields[iField].RealList.paList == nullptr)
    5498             :             {
    5499           0 :                 OGR_RawField_SetUnset(&pauFields[iField]);
    5500           0 :                 return false;
    5501             :             }
    5502       21563 :             if (nCount > 0)
    5503             :             {
    5504       19943 :                 memcpy(pauFields[iField].RealList.paList,
    5505       19943 :                        puValue->RealList.paList, sizeof(double) * nCount);
    5506             :             }
    5507       21563 :             pauFields[iField].RealList.nCount = nCount;
    5508             :         }
    5509             :     }
    5510       88513 :     else if (poFDefn->GetType() == OFTStringList)
    5511             :     {
    5512       29646 :         if (IsFieldSetAndNotNullUnsafe(iField))
    5513        5627 :             CSLDestroy(pauFields[iField].StringList.paList);
    5514             : 
    5515       29646 :         if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
    5516             :         {
    5517         272 :             pauFields[iField] = *puValue;
    5518             :         }
    5519             :         else
    5520             :         {
    5521       29374 :             char **papszNewList = nullptr;
    5522       29374 :             for (char **papszIter = puValue->StringList.paList;
    5523       84238 :                  papszIter != nullptr && *papszIter != nullptr; ++papszIter)
    5524             :             {
    5525             :                 char **papszNewList2 =
    5526       54864 :                     CSLAddStringMayFail(papszNewList, *papszIter);
    5527       54864 :                 if (papszNewList2 == nullptr)
    5528             :                 {
    5529           0 :                     CSLDestroy(papszNewList);
    5530           0 :                     OGR_RawField_SetUnset(&pauFields[iField]);
    5531           0 :                     return false;
    5532             :                 }
    5533       54864 :                 papszNewList = papszNewList2;
    5534             :             }
    5535       29374 :             pauFields[iField].StringList.paList = papszNewList;
    5536       29374 :             pauFields[iField].StringList.nCount = puValue->StringList.nCount;
    5537       29374 :             CPLAssert(CSLCount(puValue->StringList.paList) ==
    5538             :                       puValue->StringList.nCount);
    5539             :         }
    5540             :     }
    5541       58867 :     else if (poFDefn->GetType() == OFTBinary)
    5542             :     {
    5543       58867 :         if (IsFieldSetAndNotNullUnsafe(iField))
    5544         103 :             CPLFree(pauFields[iField].Binary.paData);
    5545             : 
    5546       58867 :         if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
    5547             :         {
    5548         105 :             pauFields[iField] = *puValue;
    5549             :         }
    5550             :         else
    5551             :         {
    5552      117524 :             pauFields[iField].Binary.paData = static_cast<GByte *>(
    5553       58762 :                 VSI_MALLOC_VERBOSE(puValue->Binary.nCount));
    5554       58762 :             if (pauFields[iField].Binary.paData == nullptr)
    5555             :             {
    5556           0 :                 OGR_RawField_SetUnset(&pauFields[iField]);
    5557           0 :                 return false;
    5558             :             }
    5559       58762 :             if (puValue->Binary.nCount > 0)
    5560             :             {
    5561       58719 :                 memcpy(pauFields[iField].Binary.paData, puValue->Binary.paData,
    5562       58719 :                        puValue->Binary.nCount);
    5563             :             }
    5564       58762 :             pauFields[iField].Binary.nCount = puValue->Binary.nCount;
    5565             :         }
    5566             :     }
    5567             :     else
    5568             :     {
    5569             :         // Do nothing for other field types.
    5570             :     }
    5571     4619710 :     return true;
    5572             : }
    5573             : 
    5574             : /************************************************************************/
    5575             : /*                      OGR_F_SetFieldRaw()                             */
    5576             : /************************************************************************/
    5577             : 
    5578             : /**
    5579             :  * \brief Set field.
    5580             :  *
    5581             :  * The passed value OGRField must be of exactly the same type as the
    5582             :  * target field, or an application crash may occur.  The passed value
    5583             :  * is copied, and will not be affected.  It remains the responsibility of
    5584             :  * the caller.
    5585             :  *
    5586             :  * This function is the same as the C++ method OGRFeature::SetField().
    5587             :  *
    5588             :  * @note This method has only an effect on the in-memory feature object. If
    5589             :  * this object comes from a layer and the modifications must be serialized back
    5590             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5591             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5592             :  *
    5593             :  * @param hFeat handle to the feature that owned the field.
    5594             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    5595             :  * @param psValue handle on the value to assign.
    5596             :  */
    5597             : 
    5598           0 : void OGR_F_SetFieldRaw(OGRFeatureH hFeat, int iField, const OGRField *psValue)
    5599             : 
    5600             : {
    5601           0 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldRaw");
    5602             : 
    5603           0 :     OGRFeature::FromHandle(hFeat)->SetField(iField, psValue);
    5604             : }
    5605             : 
    5606             : /************************************************************************/
    5607             : /*                            DumpReadable()                            */
    5608             : /************************************************************************/
    5609             : 
    5610             : /**
    5611             :  * \brief Dump this feature in a human readable form.
    5612             :  *
    5613             :  * This dumps the attributes, and geometry; however, it doesn't definition
    5614             :  * information (other than field types and names), nor does it report the
    5615             :  * geometry spatial reference system.
    5616             :  *
    5617             :  * A few options can be defined to change the default dump :
    5618             :  * <ul>
    5619             :  * <li>DISPLAY_FIELDS=NO : to hide the dump of the attributes</li>
    5620             :  * <li>DISPLAY_STYLE=NO : to hide the dump of the style string</li>
    5621             :  * <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
    5622             :  * <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
    5623             :  * </ul>
    5624             :  *
    5625             :  * This method is the same as the C function OGR_F_DumpReadable().
    5626             :  *
    5627             :  * @param fpOut the stream to write to, such as stdout.  If NULL stdout will
    5628             :  * be used.
    5629             :  * @param papszOptions NULL terminated list of options (may be NULL)
    5630             :  */
    5631             : 
    5632         121 : void OGRFeature::DumpReadable(FILE *fpOut, CSLConstList papszOptions) const
    5633             : 
    5634             : {
    5635         121 :     if (fpOut == nullptr)
    5636         121 :         fpOut = stdout;
    5637             : 
    5638         242 :     const auto osStr = DumpReadableAsString(papszOptions);
    5639         121 :     fprintf(fpOut, "%s", osStr.c_str());
    5640         121 : }
    5641             : 
    5642             : /************************************************************************/
    5643             : /*                       DumpReadableAsString()                         */
    5644             : /************************************************************************/
    5645             : 
    5646             : /**
    5647             :  * \brief Dump this feature in a human readable form.
    5648             :  *
    5649             :  * This dumps the attributes, and geometry; however, it doesn't definition
    5650             :  * information (other than field types and names), nor does it report the
    5651             :  * geometry spatial reference system.
    5652             :  *
    5653             :  * A few options can be defined to change the default dump :
    5654             :  * <ul>
    5655             :  * <li>DISPLAY_FIELDS=NO : to hide the dump of the attributes</li>
    5656             :  * <li>DISPLAY_STYLE=NO : to hide the dump of the style string</li>
    5657             :  * <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
    5658             :  * <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
    5659             :  * </ul>
    5660             :  *
    5661             :  * @param papszOptions NULL terminated list of options (may be NULL)
    5662             :  * @return a string with the feature representation.
    5663             :  * @since GDAL 3.7
    5664             :  */
    5665             : 
    5666         827 : std::string OGRFeature::DumpReadableAsString(CSLConstList papszOptions) const
    5667             : {
    5668         827 :     std::string osRet;
    5669             : 
    5670        1654 :     osRet += CPLOPrintf("OGRFeature(%s):" CPL_FRMT_GIB "\n", poDefn->GetName(),
    5671         827 :                         GetFID());
    5672             : 
    5673             :     const char *pszDisplayFields =
    5674         827 :         CSLFetchNameValue(papszOptions, "DISPLAY_FIELDS");
    5675         827 :     if (pszDisplayFields == nullptr || CPLTestBool(pszDisplayFields))
    5676             :     {
    5677         816 :         const int nFieldCount = GetFieldCount();
    5678        8168 :         for (int iField = 0; iField < nFieldCount; iField++)
    5679             :         {
    5680        7352 :             if (!IsFieldSet(iField))
    5681        2560 :                 continue;
    5682        4792 :             const OGRFieldDefn *poFDefn = poDefn->GetFieldDefnUnsafe(iField);
    5683             : 
    5684             :             const char *pszType =
    5685        4792 :                 (poFDefn->GetSubType() != OFSTNone)
    5686        4792 :                     ? CPLSPrintf(
    5687             :                           "%s(%s)",
    5688             :                           poFDefn->GetFieldTypeName(poFDefn->GetType()),
    5689             :                           poFDefn->GetFieldSubTypeName(poFDefn->GetSubType()))
    5690        4354 :                     : poFDefn->GetFieldTypeName(poFDefn->GetType());
    5691             : 
    5692        4792 :             osRet += CPLOPrintf("  %s (%s) = ", poFDefn->GetNameRef(), pszType);
    5693             : 
    5694        4792 :             if (IsFieldNull(iField))
    5695          45 :                 osRet += "(null)\n";
    5696             :             else
    5697        4747 :                 osRet += CPLOPrintf("%s\n", GetFieldAsString(iField));
    5698             :         }
    5699             :     }
    5700             : 
    5701         827 :     if (GetStyleString() != nullptr)
    5702             :     {
    5703             :         const char *pszDisplayStyle =
    5704           4 :             CSLFetchNameValue(papszOptions, "DISPLAY_STYLE");
    5705           4 :         if (pszDisplayStyle == nullptr || CPLTestBool(pszDisplayStyle))
    5706             :         {
    5707           4 :             osRet += CPLOPrintf("  Style = %s\n", GetStyleString());
    5708             :         }
    5709             :     }
    5710             : 
    5711         827 :     const int nGeomFieldCount = GetGeomFieldCount();
    5712         827 :     if (nGeomFieldCount > 0)
    5713             :     {
    5714             :         const char *pszDisplayGeometry =
    5715         311 :             CSLFetchNameValue(papszOptions, "DISPLAY_GEOMETRY");
    5716         311 :         if (!(pszDisplayGeometry != nullptr && EQUAL(pszDisplayGeometry, "NO")))
    5717             :         {
    5718         606 :             for (int iField = 0; iField < nGeomFieldCount; iField++)
    5719             :             {
    5720             :                 const OGRGeomFieldDefn *poFDefn =
    5721         306 :                     poDefn->GetGeomFieldDefn(iField);
    5722             : 
    5723         306 :                 if (papoGeometries[iField] != nullptr)
    5724             :                 {
    5725         303 :                     CPLStringList aosGeomOptions(papszOptions);
    5726             : 
    5727         303 :                     const auto &oCoordPrec = poFDefn->GetCoordinatePrecision();
    5728             : 
    5729         303 :                     if (oCoordPrec.dfXYResolution !=
    5730             :                         OGRGeomCoordinatePrecision::UNKNOWN)
    5731             :                     {
    5732             :                         aosGeomOptions.SetNameValue(
    5733             :                             "XY_COORD_PRECISION",
    5734             :                             CPLSPrintf("%d",
    5735             :                                        OGRGeomCoordinatePrecision::
    5736             :                                            ResolutionToPrecision(
    5737           1 :                                                oCoordPrec.dfXYResolution)));
    5738             :                     }
    5739         303 :                     if (oCoordPrec.dfZResolution !=
    5740             :                         OGRGeomCoordinatePrecision::UNKNOWN)
    5741             :                     {
    5742             :                         aosGeomOptions.SetNameValue(
    5743             :                             "Z_COORD_PRECISION",
    5744             :                             CPLSPrintf("%d",
    5745             :                                        OGRGeomCoordinatePrecision::
    5746             :                                            ResolutionToPrecision(
    5747           1 :                                                oCoordPrec.dfZResolution)));
    5748             :                     }
    5749             : 
    5750         303 :                     osRet += "  ";
    5751         355 :                     if (strlen(poFDefn->GetNameRef()) > 0 &&
    5752          52 :                         GetGeomFieldCount() > 1)
    5753          12 :                         osRet += CPLOPrintf("%s = ", poFDefn->GetNameRef());
    5754         606 :                     osRet += papoGeometries[iField]->dumpReadable(
    5755         606 :                         nullptr, aosGeomOptions.List());
    5756             :                 }
    5757             :             }
    5758             :         }
    5759             :     }
    5760             : 
    5761         827 :     osRet += "\n";
    5762         827 :     return osRet;
    5763             : }
    5764             : 
    5765             : /************************************************************************/
    5766             : /*                         OGR_F_DumpReadable()                         */
    5767             : /************************************************************************/
    5768             : 
    5769             : /**
    5770             :  * \brief Dump this feature in a human readable form.
    5771             :  *
    5772             :  * This dumps the attributes, and geometry; however, it doesn't definition
    5773             :  * information (other than field types and names), nor does it report the
    5774             :  * geometry spatial reference system.
    5775             :  *
    5776             :  * This function is the same as the C++ method OGRFeature::DumpReadable().
    5777             :  *
    5778             :  * @param hFeat handle to the feature to dump.
    5779             :  * @param fpOut the stream to write to, such as strout.
    5780             :  */
    5781             : 
    5782          31 : void OGR_F_DumpReadable(OGRFeatureH hFeat, FILE *fpOut)
    5783             : 
    5784             : {
    5785          31 :     VALIDATE_POINTER0(hFeat, "OGR_F_DumpReadable");
    5786             : 
    5787          31 :     OGRFeature::FromHandle(hFeat)->DumpReadable(fpOut);
    5788             : }
    5789             : 
    5790             : /************************************************************************/
    5791             : /*                         OGR_F_DumpReadableAsString()                 */
    5792             : /************************************************************************/
    5793             : 
    5794             : /**
    5795             :  * \brief Dump this feature in a human readable form.
    5796             :  *
    5797             :  * This dumps the attributes, and geometry; however, it doesn't include
    5798             :  * definition information (other than field types and names), nor does
    5799             :  * it report the geometry spatial reference system.
    5800             :  *
    5801             :  * A few options can be defined to change the default dump :
    5802             :  * <ul>
    5803             :  * <li>DISPLAY_FIELDS=NO : to hide the dump of the attributes</li>
    5804             :  * <li>DISPLAY_STYLE=NO : to hide the dump of the style string</li>
    5805             :  * <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
    5806             :  * <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
    5807             :  * </ul>
    5808             :  *
    5809             :  * @param hFeat handle to the feature to dump.
    5810             :  * @param papszOptions NULL terminated list of options (may be NULL)
    5811             :  * @return a string with the feature representation (to be freed with CPLFree())
    5812             :  * @since GDAL 3.8
    5813             :  */
    5814             : 
    5815          96 : char *OGR_F_DumpReadableAsString(OGRFeatureH hFeat, CSLConstList papszOptions)
    5816             : {
    5817          96 :     VALIDATE_POINTER1(hFeat, "OGR_F_DumpReadableAsString", nullptr);
    5818             : 
    5819          96 :     return CPLStrdup(OGRFeature::FromHandle(hFeat)
    5820         192 :                          ->DumpReadableAsString(papszOptions)
    5821          96 :                          .c_str());
    5822             : }
    5823             : 
    5824             : /************************************************************************/
    5825             : /*                               GetFID()                               */
    5826             : /************************************************************************/
    5827             : 
    5828             : /**
    5829             :  * \fn GIntBig OGRFeature::GetFID() const;
    5830             :  *
    5831             :  * \brief Get feature identifier.
    5832             :  *
    5833             :  * This method is the same as the C function OGR_F_GetFID().
    5834             :  *
    5835             :  * @return feature id or OGRNullFID if none has been assigned.
    5836             :  */
    5837             : 
    5838             : /************************************************************************/
    5839             : /*                            OGR_F_GetFID()                          */
    5840             : /************************************************************************/
    5841             : 
    5842             : /**
    5843             :  * \brief Get feature identifier.
    5844             :  *
    5845             :  * This function is the same as the C++ method OGRFeature::GetFID().
    5846             :  *
    5847             :  * @param hFeat handle to the feature from which to get the feature
    5848             :  * identifier.
    5849             :  * @return feature id or OGRNullFID if none has been assigned.
    5850             :  */
    5851             : 
    5852        5367 : GIntBig OGR_F_GetFID(OGRFeatureH hFeat)
    5853             : 
    5854             : {
    5855        5367 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFID", 0);
    5856             : 
    5857        5367 :     return OGRFeature::FromHandle(hFeat)->GetFID();
    5858             : }
    5859             : 
    5860             : /************************************************************************/
    5861             : /*                               SetFID()                               */
    5862             : /************************************************************************/
    5863             : 
    5864             : /**
    5865             :  * \brief Set the feature identifier.
    5866             :  *
    5867             :  * For specific types of features this operation may fail on illegal
    5868             :  * features ids.  Generally it always succeeds.  Feature ids should be
    5869             :  * greater than or equal to zero, with the exception of OGRNullFID (-1)
    5870             :  * indicating that the feature id is unknown.
    5871             :  *
    5872             :  * This method is the same as the C function OGR_F_SetFID().
    5873             :  *
    5874             :  * @param nFIDIn the new feature identifier value to assign.
    5875             :  *
    5876             :  * @return On success OGRERR_NONE, or on failure some other value.
    5877             :  */
    5878             : 
    5879     3049450 : OGRErr OGRFeature::SetFID(GIntBig nFIDIn)
    5880             : 
    5881             : {
    5882     3049450 :     nFID = nFIDIn;
    5883             : 
    5884     3049450 :     return OGRERR_NONE;
    5885             : }
    5886             : 
    5887             : /************************************************************************/
    5888             : /*                            OGR_F_SetFID()                            */
    5889             : /************************************************************************/
    5890             : 
    5891             : /**
    5892             :  * \brief Set the feature identifier.
    5893             :  *
    5894             :  * For specific types of features this operation may fail on illegal
    5895             :  * features ids.  Generally it always succeeds.  Feature ids should be
    5896             :  * greater than or equal to zero, with the exception of OGRNullFID (-1)
    5897             :  * indicating that the feature id is unknown.
    5898             :  *
    5899             :  * This function is the same as the C++ method OGRFeature::SetFID().
    5900             :  *
    5901             :  * @param hFeat handle to the feature to set the feature id to.
    5902             :  * @param nFID the new feature identifier value to assign.
    5903             :  *
    5904             :  * @return On success OGRERR_NONE, or on failure some other value.
    5905             :  */
    5906             : 
    5907      170808 : OGRErr OGR_F_SetFID(OGRFeatureH hFeat, GIntBig nFID)
    5908             : 
    5909             : {
    5910      170808 :     VALIDATE_POINTER1(hFeat, "OGR_F_SetFID", OGRERR_FAILURE);
    5911             : 
    5912      170808 :     return OGRFeature::FromHandle(hFeat)->SetFID(nFID);
    5913             : }
    5914             : 
    5915             : /************************************************************************/
    5916             : /*                               Equal()                                */
    5917             : /************************************************************************/
    5918             : 
    5919             : /**
    5920             :  * \brief Test if two features are the same.
    5921             :  *
    5922             :  * Two features are considered equal if the share them (pointer equality)
    5923             :  * same OGRFeatureDefn, have the same field values, and the same geometry
    5924             :  * (as tested by OGRGeometry::Equal()) as well as the same feature id.
    5925             :  *
    5926             :  * This method is the same as the C function OGR_F_Equal().
    5927             :  *
    5928             :  * @param poFeature the other feature to test this one against.
    5929             :  *
    5930             :  * @return TRUE if they are equal, otherwise FALSE.
    5931             :  */
    5932             : 
    5933       56414 : OGRBoolean OGRFeature::Equal(const OGRFeature *poFeature) const
    5934             : 
    5935             : {
    5936       56414 :     if (poFeature == this)
    5937           1 :         return TRUE;
    5938             : 
    5939       56413 :     if (GetFID() != poFeature->GetFID())
    5940       53304 :         return FALSE;
    5941             : 
    5942        3109 :     if (GetDefnRef() != poFeature->GetDefnRef())
    5943          11 :         return FALSE;
    5944             : 
    5945        3098 :     const int nFields = GetDefnRef()->GetFieldCountUnsafe();
    5946       27257 :     for (int i = 0; i < nFields; i++)
    5947             :     {
    5948       24269 :         if (IsFieldSet(i) != poFeature->IsFieldSet(i))
    5949           2 :             return FALSE;
    5950       24267 :         if (IsFieldNull(i) != poFeature->IsFieldNull(i))
    5951           0 :             return FALSE;
    5952       24267 :         if (!IsFieldSetAndNotNullUnsafe(i))
    5953        3552 :             continue;
    5954             : 
    5955       20715 :         switch (GetDefnRef()->GetFieldDefnUnsafe(i)->GetType())
    5956             :         {
    5957        5666 :             case OFTInteger:
    5958        5666 :                 if (GetFieldAsInteger(i) != poFeature->GetFieldAsInteger(i))
    5959          18 :                     return FALSE;
    5960        5648 :                 break;
    5961             : 
    5962         667 :             case OFTInteger64:
    5963         667 :                 if (GetFieldAsInteger64(i) != poFeature->GetFieldAsInteger64(i))
    5964           4 :                     return FALSE;
    5965         663 :                 break;
    5966             : 
    5967        4225 :             case OFTReal:
    5968             :             {
    5969        4225 :                 const double dfVal1 = GetFieldAsDouble(i);
    5970        4225 :                 const double dfVal2 = poFeature->GetFieldAsDouble(i);
    5971        4225 :                 if (std::isnan(dfVal1))
    5972             :                 {
    5973           7 :                     if (!std::isnan(dfVal2))
    5974           1 :                         return FALSE;
    5975             :                 }
    5976        4218 :                 else if (std::isnan(dfVal2))
    5977             :                 {
    5978           1 :                     return FALSE;
    5979             :                 }
    5980        4217 :                 else if (dfVal1 != dfVal2)
    5981             :                 {
    5982          16 :                     return FALSE;
    5983             :                 }
    5984        4207 :                 break;
    5985             :             }
    5986             : 
    5987        5560 :             case OFTString:
    5988        5560 :                 if (strcmp(GetFieldAsString(i),
    5989        5560 :                            poFeature->GetFieldAsString(i)) != 0)
    5990          10 :                     return FALSE;
    5991        5550 :                 break;
    5992             : 
    5993         447 :             case OFTIntegerList:
    5994             :             {
    5995         447 :                 int nCount1 = 0;
    5996         447 :                 int nCount2 = 0;
    5997         447 :                 const int *pnList1 = GetFieldAsIntegerList(i, &nCount1);
    5998             :                 const int *pnList2 =
    5999         447 :                     poFeature->GetFieldAsIntegerList(i, &nCount2);
    6000         447 :                 if (nCount1 != nCount2)
    6001           4 :                     return FALSE;
    6002        1247 :                 for (int j = 0; j < nCount1; j++)
    6003             :                 {
    6004         804 :                     if (pnList1[j] != pnList2[j])
    6005           2 :                         return FALSE;
    6006             :                 }
    6007         443 :                 break;
    6008             :             }
    6009             : 
    6010         168 :             case OFTInteger64List:
    6011             :             {
    6012         168 :                 int nCount1 = 0;
    6013         168 :                 int nCount2 = 0;
    6014         168 :                 const GIntBig *pnList1 = GetFieldAsInteger64List(i, &nCount1);
    6015             :                 const GIntBig *pnList2 =
    6016         168 :                     poFeature->GetFieldAsInteger64List(i, &nCount2);
    6017         168 :                 if (nCount1 != nCount2)
    6018           0 :                     return FALSE;
    6019         497 :                 for (int j = 0; j < nCount1; j++)
    6020             :                 {
    6021         329 :                     if (pnList1[j] != pnList2[j])
    6022           0 :                         return FALSE;
    6023             :                 }
    6024         168 :                 break;
    6025             :             }
    6026             : 
    6027         326 :             case OFTRealList:
    6028             :             {
    6029         326 :                 int nCount1 = 0;
    6030         326 :                 int nCount2 = 0;
    6031         326 :                 const double *padfList1 = GetFieldAsDoubleList(i, &nCount1);
    6032             :                 const double *padfList2 =
    6033         326 :                     poFeature->GetFieldAsDoubleList(i, &nCount2);
    6034         326 :                 if (nCount1 != nCount2)
    6035           6 :                     return FALSE;
    6036         928 :                 for (int j = 0; j < nCount1; j++)
    6037             :                 {
    6038         608 :                     const double dfVal1 = padfList1[j];
    6039         608 :                     const double dfVal2 = padfList2[j];
    6040         608 :                     if (std::isnan(dfVal1))
    6041             :                     {
    6042         126 :                         if (!std::isnan(dfVal2))
    6043           1 :                             return FALSE;
    6044             :                     }
    6045         482 :                     else if (std::isnan(dfVal2))
    6046             :                     {
    6047           1 :                         return FALSE;
    6048             :                     }
    6049         481 :                     else if (dfVal1 != dfVal2)
    6050             :                     {
    6051           2 :                         return FALSE;
    6052             :                     }
    6053             :                 }
    6054         320 :                 break;
    6055             :             }
    6056             : 
    6057         170 :             case OFTStringList:
    6058             :             {
    6059         170 :                 int nCount1 = 0;
    6060         170 :                 int nCount2 = 0;
    6061         170 :                 char **papszList1 = GetFieldAsStringList(i);
    6062         170 :                 char **papszList2 = poFeature->GetFieldAsStringList(i);
    6063         170 :                 nCount1 = CSLCount(papszList1);
    6064         170 :                 nCount2 = CSLCount(papszList2);
    6065         170 :                 if (nCount1 != nCount2)
    6066           2 :                     return FALSE;
    6067         430 :                 for (int j = 0; j < nCount1; j++)
    6068             :                 {
    6069         264 :                     if (strcmp(papszList1[j], papszList2[j]) != 0)
    6070           2 :                         return FALSE;
    6071             :                 }
    6072         166 :                 break;
    6073             :             }
    6074             : 
    6075        1472 :             case OFTTime:
    6076             :             case OFTDate:
    6077             :             case OFTDateTime:
    6078             :             {
    6079        1472 :                 int nYear1 = 0;
    6080        1472 :                 int nMonth1 = 0;
    6081        1472 :                 int nDay1 = 0;
    6082        1472 :                 int nHour1 = 0;
    6083        1472 :                 int nMinute1 = 0;
    6084        1472 :                 int nTZFlag1 = 0;
    6085        1472 :                 int nYear2 = 0;
    6086        1472 :                 int nMonth2 = 0;
    6087        1472 :                 int nDay2 = 0;
    6088        1472 :                 int nHour2 = 0;
    6089        1472 :                 int nMinute2 = 0;
    6090        1472 :                 int nTZFlag2 = 0;
    6091        1472 :                 float fSecond1 = 0.0f;
    6092        1472 :                 float fSecond2 = 0.0f;
    6093        1472 :                 GetFieldAsDateTime(i, &nYear1, &nMonth1, &nDay1, &nHour1,
    6094             :                                    &nMinute1, &fSecond1, &nTZFlag1);
    6095        1472 :                 poFeature->GetFieldAsDateTime(i, &nYear2, &nMonth2, &nDay2,
    6096             :                                               &nHour2, &nMinute2, &fSecond2,
    6097             :                                               &nTZFlag2);
    6098             : 
    6099        1472 :                 if (!(nYear1 == nYear2 && nMonth1 == nMonth2 &&
    6100        1460 :                       nDay1 == nDay2 && nHour1 == nHour2 &&
    6101        1448 :                       nMinute1 == nMinute2 && fSecond1 == fSecond2 &&
    6102        1436 :                       nTZFlag1 == nTZFlag2))
    6103          42 :                     return FALSE;
    6104        1430 :                 break;
    6105             :             }
    6106             : 
    6107        2014 :             case OFTBinary:
    6108             :             {
    6109        2014 :                 int nCount1 = 0;
    6110        2014 :                 int nCount2 = 0;
    6111        2014 :                 GByte *pabyData1 = GetFieldAsBinary(i, &nCount1);
    6112        2014 :                 GByte *pabyData2 = poFeature->GetFieldAsBinary(i, &nCount2);
    6113        2014 :                 if (nCount1 != nCount2)
    6114           2 :                     return FALSE;
    6115        2012 :                 if (memcmp(pabyData1, pabyData2, nCount1) != 0)
    6116           0 :                     return FALSE;
    6117        2012 :                 break;
    6118             :             }
    6119             : 
    6120           0 :             default:
    6121           0 :                 if (strcmp(GetFieldAsString(i),
    6122           0 :                            poFeature->GetFieldAsString(i)) != 0)
    6123           0 :                     return FALSE;
    6124           0 :                 break;
    6125             :         }
    6126             :     }
    6127             : 
    6128        2988 :     const int nGeomFieldCount = GetGeomFieldCount();
    6129        5672 :     for (int i = 0; i < nGeomFieldCount; i++)
    6130             :     {
    6131        2796 :         const OGRGeometry *poThisGeom = GetGeomFieldRef(i);
    6132        2796 :         const OGRGeometry *poOtherGeom = poFeature->GetGeomFieldRef(i);
    6133             : 
    6134        2796 :         if (poThisGeom == nullptr && poOtherGeom != nullptr)
    6135           3 :             return FALSE;
    6136             : 
    6137        2793 :         if (poThisGeom != nullptr && poOtherGeom == nullptr)
    6138           4 :             return FALSE;
    6139             : 
    6140        5398 :         if (poThisGeom != nullptr && poOtherGeom != nullptr &&
    6141        2609 :             (!poThisGeom->Equals(poOtherGeom)))
    6142         105 :             return FALSE;
    6143             :     }
    6144             : 
    6145        2876 :     return TRUE;
    6146             : }
    6147             : 
    6148             : /************************************************************************/
    6149             : /*                            OGR_F_Equal()                             */
    6150             : /************************************************************************/
    6151             : 
    6152             : /**
    6153             :  * \brief Test if two features are the same.
    6154             :  *
    6155             :  * Two features are considered equal if the share them (handle equality)
    6156             :  * same OGRFeatureDefn, have the same field values, and the same geometry
    6157             :  * (as tested by OGR_G_Equal()) as well as the same feature id.
    6158             :  *
    6159             :  * This function is the same as the C++ method OGRFeature::Equal().
    6160             :  *
    6161             :  * @param hFeat handle to one of the feature.
    6162             :  * @param hOtherFeat handle to the other feature to test this one against.
    6163             :  *
    6164             :  * @return TRUE if they are equal, otherwise FALSE.
    6165             :  */
    6166             : 
    6167         109 : int OGR_F_Equal(OGRFeatureH hFeat, OGRFeatureH hOtherFeat)
    6168             : 
    6169             : {
    6170         109 :     VALIDATE_POINTER1(hFeat, "OGR_F_Equal", 0);
    6171         109 :     VALIDATE_POINTER1(hOtherFeat, "OGR_F_Equal", 0);
    6172             : 
    6173         218 :     return OGRFeature::FromHandle(hFeat)->Equal(
    6174         109 :         OGRFeature::FromHandle(hOtherFeat));
    6175             : }
    6176             : 
    6177             : /************************************************************************/
    6178             : /*                              SetFrom()                               */
    6179             : /************************************************************************/
    6180             : 
    6181             : /**
    6182             :  * \brief Set one feature from another.
    6183             :  *
    6184             :  * Overwrite the contents of this feature from the geometry and attributes
    6185             :  * of another.  The poSrcFeature does not need to have the same
    6186             :  * OGRFeatureDefn.  Field values are copied by corresponding field names.
    6187             :  * Field types do not have to exactly match.  SetField() method conversion
    6188             :  * rules will be applied as needed.
    6189             :  *
    6190             :  * This method is the same as the C function OGR_F_SetFrom().
    6191             :  *
    6192             :  * @param poSrcFeature the feature from which geometry, and field values will
    6193             :  * be copied.
    6194             :  *
    6195             :  * @param bForgiving TRUE if the operation should continue despite lacking
    6196             :  * output fields matching some of the source fields.
    6197             :  *
    6198             :  * @return OGRERR_NONE if the operation succeeds, even if some values are
    6199             :  * not transferred, otherwise an error code.
    6200             :  */
    6201             : 
    6202        4908 : OGRErr OGRFeature::SetFrom(const OGRFeature *poSrcFeature, int bForgiving)
    6203             : 
    6204             : {
    6205        4908 :     const auto &oMap = poDefn->ComputeMapForSetFrom(poSrcFeature->GetDefnRef(),
    6206        9816 :                                                     CPL_TO_BOOL(bForgiving));
    6207        4908 :     if (oMap.empty())
    6208             :     {
    6209         228 :         if (poSrcFeature->GetFieldCount())
    6210           0 :             return OGRERR_FAILURE;
    6211         228 :         int dummy = 0;
    6212         228 :         return SetFrom(poSrcFeature, &dummy, bForgiving);
    6213             :     }
    6214        4680 :     return SetFrom(poSrcFeature, oMap.data(), bForgiving);
    6215             : }
    6216             : 
    6217             : /************************************************************************/
    6218             : /*                           OGR_F_SetFrom()                            */
    6219             : /************************************************************************/
    6220             : 
    6221             : /**
    6222             :  * \brief Set one feature from another.
    6223             :  *
    6224             :  * Overwrite the contents of this feature from the geometry and attributes
    6225             :  * of another.  The hOtherFeature does not need to have the same
    6226             :  * OGRFeatureDefn.  Field values are copied by corresponding field names.
    6227             :  * Field types do not have to exactly match.  OGR_F_SetField*() function
    6228             :  * conversion rules will be applied as needed.
    6229             :  *
    6230             :  * This function is the same as the C++ method OGRFeature::SetFrom().
    6231             :  *
    6232             :  * @param hFeat handle to the feature to set to.
    6233             :  * @param hOtherFeat handle to the feature from which geometry,
    6234             :  * and field values will be copied.
    6235             :  *
    6236             :  * @param bForgiving TRUE if the operation should continue despite lacking
    6237             :  * output fields matching some of the source fields.
    6238             :  *
    6239             :  * @return OGRERR_NONE if the operation succeeds, even if some values are
    6240             :  * not transferred, otherwise an error code.
    6241             :  */
    6242             : 
    6243        1812 : OGRErr OGR_F_SetFrom(OGRFeatureH hFeat, OGRFeatureH hOtherFeat, int bForgiving)
    6244             : 
    6245             : {
    6246        1812 :     VALIDATE_POINTER1(hFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
    6247        1812 :     VALIDATE_POINTER1(hOtherFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
    6248             : 
    6249        3624 :     return OGRFeature::FromHandle(hFeat)->SetFrom(
    6250        3624 :         OGRFeature::FromHandle(hOtherFeat), bForgiving);
    6251             : }
    6252             : 
    6253             : /************************************************************************/
    6254             : /*                              SetFrom()                               */
    6255             : /************************************************************************/
    6256             : 
    6257             : /**
    6258             :  * \brief Set one feature from another.
    6259             :  *
    6260             :  * Overwrite the contents of this feature from the geometry and attributes
    6261             :  * of another.  The poSrcFeature does not need to have the same
    6262             :  * OGRFeatureDefn.  Field values are copied according to the provided indices
    6263             :  * map. Field types do not have to exactly match.  SetField() method
    6264             :  * conversion rules will be applied as needed. This is more efficient than
    6265             :  * OGR_F_SetFrom() in that this doesn't lookup the fields by their names.
    6266             :  * Particularly useful when the field names don't match.
    6267             :  *
    6268             :  * This method is the same as the C function OGR_F_SetFromWithMap().
    6269             :  *
    6270             :  * @param poSrcFeature the feature from which geometry, and field values will
    6271             :  * be copied.
    6272             :  *
    6273             :  * @param panMap Array of the indices of the feature's fields
    6274             :  * stored at the corresponding index of the source feature's fields. A value of
    6275             :  * -1 should be used to ignore the source's field. The array should not be NULL
    6276             :  * and be as long as the number of fields in the source feature.
    6277             :  *
    6278             :  * @param bForgiving TRUE if the operation should continue despite lacking
    6279             :  * output fields matching some of the source fields.
    6280             :  *
    6281             :  * @param bUseISO8601ForDateTimeAsString true if datetime fields
    6282             :  * converted to string should use ISO8601 formatting rather than OGR own format.
    6283             :  *
    6284             :  * @return OGRERR_NONE if the operation succeeds, even if some values are
    6285             :  * not transferred, otherwise an error code.
    6286             :  */
    6287             : 
    6288        8957 : OGRErr OGRFeature::SetFrom(const OGRFeature *poSrcFeature, const int *panMap,
    6289             :                            int bForgiving, bool bUseISO8601ForDateTimeAsString)
    6290             : 
    6291             : {
    6292        8957 :     if (poSrcFeature == this)
    6293           0 :         return OGRERR_FAILURE;
    6294             : 
    6295        8957 :     SetFID(OGRNullFID);
    6296             : 
    6297             :     /* -------------------------------------------------------------------- */
    6298             :     /*      Set the geometry.                                               */
    6299             :     /* -------------------------------------------------------------------- */
    6300        8957 :     if (GetGeomFieldCount() == 1)
    6301             :     {
    6302        7637 :         const OGRGeomFieldDefn *poGFieldDefn = GetGeomFieldDefnRef(0);
    6303             : 
    6304        7637 :         int iSrc = poSrcFeature->GetGeomFieldIndex(poGFieldDefn->GetNameRef());
    6305        7637 :         if (iSrc >= 0)
    6306        6281 :             SetGeomField(0, poSrcFeature->GetGeomFieldRef(iSrc));
    6307             :         else
    6308             :             // Whatever the geometry field names are.  For backward
    6309             :             // compatibility.
    6310        1356 :             SetGeomField(0, poSrcFeature->GetGeomFieldRef(0));
    6311             :     }
    6312             :     else
    6313             :     {
    6314        2127 :         for (int i = 0; i < GetGeomFieldCount(); i++)
    6315             :         {
    6316         807 :             const OGRGeomFieldDefn *poGFieldDefn = GetGeomFieldDefnRef(i);
    6317             : 
    6318             :             const int iSrc =
    6319         807 :                 poSrcFeature->GetGeomFieldIndex(poGFieldDefn->GetNameRef());
    6320         807 :             if (iSrc >= 0)
    6321         718 :                 SetGeomField(i, poSrcFeature->GetGeomFieldRef(iSrc));
    6322             :             else
    6323          89 :                 SetGeomField(i, nullptr);
    6324             :         }
    6325             :     }
    6326             : 
    6327             :     /* -------------------------------------------------------------------- */
    6328             :     /*      Copy feature style string.                                      */
    6329             :     /* -------------------------------------------------------------------- */
    6330        8957 :     SetStyleString(poSrcFeature->GetStyleString());
    6331             : 
    6332             :     /* -------------------------------------------------------------------- */
    6333             :     /*      Copy native data.                                               */
    6334             :     /* -------------------------------------------------------------------- */
    6335        8957 :     SetNativeData(poSrcFeature->GetNativeData());
    6336        8957 :     SetNativeMediaType(poSrcFeature->GetNativeMediaType());
    6337             : 
    6338             :     /* -------------------------------------------------------------------- */
    6339             :     /*      Set the fields by name.                                         */
    6340             :     /* -------------------------------------------------------------------- */
    6341             : 
    6342        8957 :     const OGRErr eErr = SetFieldsFrom(poSrcFeature, panMap, bForgiving,
    6343             :                                       bUseISO8601ForDateTimeAsString);
    6344        8957 :     if (eErr != OGRERR_NONE)
    6345           0 :         return eErr;
    6346             : 
    6347        8957 :     return OGRERR_NONE;
    6348             : }
    6349             : 
    6350             : /************************************************************************/
    6351             : /*                      OGR_F_SetFromWithMap()                          */
    6352             : /************************************************************************/
    6353             : 
    6354             : /**
    6355             :  * \brief Set one feature from another.
    6356             :  *
    6357             :  * Overwrite the contents of this feature from the geometry and attributes
    6358             :  * of another.  The hOtherFeature does not need to have the same
    6359             :  * OGRFeatureDefn.  Field values are copied according to the provided indices
    6360             :  * map. Field types do not have to exactly match.  OGR_F_SetField*() function
    6361             :  * conversion rules will be applied as needed. This is more efficient than
    6362             :  * OGR_F_SetFrom() in that this doesn't lookup the fields by their names.
    6363             :  * Particularly useful when the field names don't match.
    6364             :  *
    6365             :  * This function is the same as the C++ method OGRFeature::SetFrom().
    6366             :  *
    6367             :  * @param hFeat handle to the feature to set to.
    6368             :  * @param hOtherFeat handle to the feature from which geometry,
    6369             :  * and field values will be copied.
    6370             :  *
    6371             :  * @param panMap Array of the indices of the destination feature's fields
    6372             :  * stored at the corresponding index of the source feature's fields. A value of
    6373             :  * -1 should be used to ignore the source's field. The array should not be NULL
    6374             :  * and be as long as the number of fields in the source feature.
    6375             :  *
    6376             :  * @param bForgiving TRUE if the operation should continue despite lacking
    6377             :  * output fields matching some of the source fields.
    6378             :  *
    6379             :  * @return OGRERR_NONE if the operation succeeds, even if some values are
    6380             :  * not transferred, otherwise an error code.
    6381             :  */
    6382             : 
    6383          10 : OGRErr OGR_F_SetFromWithMap(OGRFeatureH hFeat, OGRFeatureH hOtherFeat,
    6384             :                             int bForgiving, const int *panMap)
    6385             : 
    6386             : {
    6387          10 :     VALIDATE_POINTER1(hFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
    6388          10 :     VALIDATE_POINTER1(hOtherFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
    6389          10 :     VALIDATE_POINTER1(panMap, "OGR_F_SetFrom", OGRERR_FAILURE);
    6390             : 
    6391          20 :     return OGRFeature::FromHandle(hFeat)->SetFrom(
    6392          20 :         OGRFeature::FromHandle(hOtherFeat), panMap, bForgiving);
    6393             : }
    6394             : 
    6395             : /************************************************************************/
    6396             : /*                           SetFieldsFrom()                            */
    6397             : /************************************************************************/
    6398             : 
    6399             : /**
    6400             :  * \brief Set fields from another feature.
    6401             :  *
    6402             :  * Overwrite the fields of this feature from the attributes of
    6403             :  * another. The FID and the style string are not set. The poSrcFeature
    6404             :  * does not need to have the same OGRFeatureDefn.  Field values are
    6405             :  * copied according to the provided indices map. Field types do not
    6406             :  * have to exactly match.  SetField() method conversion rules will be
    6407             :  * applied as needed. This is more efficient than OGR_F_SetFrom() in
    6408             :  * that this doesn't lookup the fields by their names.  Particularly
    6409             :  * useful when the field names don't match.
    6410             :  *
    6411             :  * @param poSrcFeature the feature from which geometry, and field values will
    6412             :  * be copied.
    6413             :  *
    6414             :  * @param panMap Array of the indices of the feature's fields
    6415             :  * stored at the corresponding index of the source feature's fields. A value of
    6416             :  * -1 should be used to ignore the source's field. The array should not be NULL
    6417             :  * and be as long as the number of fields in the source feature.
    6418             :  *
    6419             :  * @param bForgiving TRUE if the operation should continue despite lacking
    6420             :  * output fields matching some of the source fields.
    6421             :  *
    6422             :  * @param bUseISO8601ForDateTimeAsString true if datetime fields
    6423             :  * converted to string should use ISO8601 formatting rather than OGR own format.
    6424             :  *
    6425             :  * @return OGRERR_NONE if the operation succeeds, even if some values are
    6426             :  * not transferred, otherwise an error code.
    6427             :  */
    6428             : 
    6429       10698 : OGRErr OGRFeature::SetFieldsFrom(const OGRFeature *poSrcFeature,
    6430             :                                  const int *panMap, int bForgiving,
    6431             :                                  bool bUseISO8601ForDateTimeAsString)
    6432             : 
    6433             : {
    6434       10698 :     const int nSrcFieldCount = poSrcFeature->poDefn->GetFieldCountUnsafe();
    6435       10698 :     const int nFieldCount = poDefn->GetFieldCountUnsafe();
    6436      115606 :     for (int iField = 0; iField < nSrcFieldCount; iField++)
    6437             :     {
    6438      104908 :         const int iDstField = panMap[iField];
    6439             : 
    6440      104908 :         if (iDstField < 0)
    6441        3471 :             continue;
    6442             : 
    6443      101437 :         if (nFieldCount <= iDstField)
    6444           0 :             return OGRERR_FAILURE;
    6445             : 
    6446      101437 :         if (!poSrcFeature->IsFieldSetUnsafe(iField))
    6447             :         {
    6448        9467 :             UnsetField(iDstField);
    6449        9467 :             continue;
    6450             :         }
    6451             : 
    6452       91970 :         if (poSrcFeature->IsFieldNullUnsafe(iField))
    6453             :         {
    6454        1735 :             SetFieldNull(iDstField);
    6455        1735 :             continue;
    6456             :         }
    6457             : 
    6458             :         const auto eSrcType =
    6459       90235 :             poSrcFeature->poDefn->GetFieldDefnUnsafe(iField)->GetType();
    6460       90235 :         const auto eDstType = poDefn->GetFieldDefnUnsafe(iDstField)->GetType();
    6461       90235 :         if (eSrcType == eDstType)
    6462             :         {
    6463       87185 :             if (eSrcType == OFTInteger)
    6464             :             {
    6465       30576 :                 SetFieldSameTypeUnsafe(
    6466             :                     iDstField, poSrcFeature->GetFieldAsIntegerUnsafe(iField));
    6467       30576 :                 continue;
    6468             :             }
    6469       56609 :             if (eSrcType == OFTInteger64)
    6470             :             {
    6471        3151 :                 SetFieldSameTypeUnsafe(
    6472             :                     iDstField, poSrcFeature->GetFieldAsInteger64Unsafe(iField));
    6473        3151 :                 continue;
    6474             :             }
    6475       53458 :             if (eSrcType == OFTReal)
    6476             :             {
    6477       12481 :                 SetFieldSameTypeUnsafe(
    6478             :                     iDstField, poSrcFeature->GetFieldAsDoubleUnsafe(iField));
    6479       12481 :                 continue;
    6480             :             }
    6481       40977 :             if (eSrcType == OFTString)
    6482             :             {
    6483       40188 :                 if (IsFieldSetAndNotNullUnsafe(iDstField))
    6484        1498 :                     CPLFree(pauFields[iDstField].String);
    6485             : 
    6486       40188 :                 SetFieldSameTypeUnsafe(
    6487             :                     iDstField,
    6488             :                     VSI_STRDUP_VERBOSE(
    6489             :                         poSrcFeature->GetFieldAsStringUnsafe(iField)));
    6490       40188 :                 continue;
    6491             :             }
    6492             :         }
    6493             : 
    6494             :         // Check if we must convert list types to JSON
    6495        3839 :         if (eDstType == OFTString)
    6496             :         {
    6497             :             const auto eDstSubType =
    6498          61 :                 poDefn->GetFieldDefnUnsafe(iDstField)->GetSubType();
    6499          61 :             if (eDstSubType == OFSTJSON &&
    6500          17 :                 (eSrcType == OFTIntegerList || eSrcType == OFTInteger64List ||
    6501           6 :                  eSrcType == OFTRealList || eSrcType == OFTStringList))
    6502             :             {
    6503          26 :                 char *pszVal = poSrcFeature->GetFieldAsSerializedJSon(iField);
    6504          26 :                 if (pszVal)
    6505             :                 {
    6506          26 :                     SetField(iDstField, pszVal);
    6507          26 :                     CPLFree(pszVal);
    6508          26 :                     continue;
    6509             :                 }
    6510             :             }
    6511             :         }
    6512             : 
    6513        3813 :         switch (eSrcType)
    6514             :         {
    6515        1205 :             case OFTInteger:
    6516        1205 :                 SetField(iDstField,
    6517             :                          poSrcFeature->GetFieldAsIntegerUnsafe(iField));
    6518        1205 :                 break;
    6519             : 
    6520        1613 :             case OFTInteger64:
    6521        1613 :                 SetField(iDstField,
    6522             :                          poSrcFeature->GetFieldAsInteger64Unsafe(iField));
    6523        1613 :                 break;
    6524             : 
    6525          25 :             case OFTReal:
    6526          25 :                 SetField(iDstField,
    6527             :                          poSrcFeature->GetFieldAsDoubleUnsafe(iField));
    6528          25 :                 break;
    6529             : 
    6530          83 :             case OFTString:
    6531          83 :                 SetField(iDstField,
    6532             :                          poSrcFeature->GetFieldAsStringUnsafe(iField));
    6533          83 :                 break;
    6534             : 
    6535         270 :             case OFTIntegerList:
    6536             :             {
    6537         270 :                 if (eDstType == OFTString)
    6538             :                 {
    6539           2 :                     SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
    6540             :                 }
    6541             :                 else
    6542             :                 {
    6543         268 :                     int nCount = 0;
    6544             :                     const int *panValues =
    6545         268 :                         poSrcFeature->GetFieldAsIntegerList(iField, &nCount);
    6546         268 :                     SetField(iDstField, nCount, panValues);
    6547             :                 }
    6548             :             }
    6549         270 :             break;
    6550             : 
    6551          47 :             case OFTInteger64List:
    6552             :             {
    6553          47 :                 if (eDstType == OFTString)
    6554             :                 {
    6555           1 :                     SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
    6556             :                 }
    6557             :                 else
    6558             :                 {
    6559          46 :                     int nCount = 0;
    6560             :                     const GIntBig *panValues =
    6561          46 :                         poSrcFeature->GetFieldAsInteger64List(iField, &nCount);
    6562          46 :                     SetField(iDstField, nCount, panValues);
    6563             :                 }
    6564             :             }
    6565          47 :             break;
    6566             : 
    6567          86 :             case OFTRealList:
    6568             :             {
    6569          86 :                 if (eDstType == OFTString)
    6570             :                 {
    6571           2 :                     SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
    6572             :                 }
    6573             :                 else
    6574             :                 {
    6575          84 :                     int nCount = 0;
    6576             :                     const double *padfValues =
    6577          84 :                         poSrcFeature->GetFieldAsDoubleList(iField, &nCount);
    6578          84 :                     SetField(iDstField, nCount, padfValues);
    6579             :                 }
    6580             :             }
    6581          86 :             break;
    6582             : 
    6583         412 :             case OFTDate:
    6584             :             case OFTDateTime:
    6585             :             case OFTTime:
    6586             :             {
    6587         412 :                 if (eDstType == OFTDate || eDstType == OFTTime ||
    6588             :                     eDstType == OFTDateTime)
    6589             :                 {
    6590         380 :                     SetField(iDstField, poSrcFeature->GetRawFieldRef(iField));
    6591             :                 }
    6592          32 :                 else if (eDstType == OFTString || eDstType == OFTStringList)
    6593             :                 {
    6594          22 :                     SetField(iDstField,
    6595           4 :                              eSrcType == OFTDateTime &&
    6596             :                                      bUseISO8601ForDateTimeAsString
    6597           2 :                                  ? poSrcFeature->GetFieldAsISO8601DateTime(
    6598             :                                        iField, nullptr)
    6599           9 :                                  : poSrcFeature->GetFieldAsString(iField));
    6600             :                 }
    6601          21 :                 else if (!bForgiving)
    6602           0 :                     return OGRERR_FAILURE;
    6603         412 :                 break;
    6604             :             }
    6605             : 
    6606          72 :             default:
    6607             :             {
    6608          72 :                 if (eSrcType == eDstType)
    6609             :                 {
    6610          47 :                     SetField(iDstField, poSrcFeature->GetRawFieldRef(iField));
    6611             :                 }
    6612          25 :                 else if (eDstType == OFTString || eDstType == OFTStringList)
    6613             :                 {
    6614           6 :                     SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
    6615             :                 }
    6616          19 :                 else if (!bForgiving)
    6617           0 :                     return OGRERR_FAILURE;
    6618          72 :                 break;
    6619             :             }
    6620             :         }
    6621             :     }
    6622             : 
    6623       10698 :     return OGRERR_NONE;
    6624             : }
    6625             : 
    6626             : /************************************************************************/
    6627             : /*                             GetStyleString()                         */
    6628             : /************************************************************************/
    6629             : 
    6630             : /**
    6631             :  * \brief Fetch style string for this feature.
    6632             :  *
    6633             :  * Set the OGR Feature Style Specification for details on the format of
    6634             :  * this string, and ogr_featurestyle.h for services available to parse it.
    6635             :  *
    6636             :  * This method is the same as the C function OGR_F_GetStyleString().
    6637             :  *
    6638             :  * @return a reference to a representation in string format, or NULL if
    6639             :  * there isn't one.
    6640             :  */
    6641             : 
    6642       60751 : const char *OGRFeature::GetStyleString() const
    6643             : {
    6644       60751 :     if (m_pszStyleString)
    6645        8731 :         return m_pszStyleString;
    6646             : 
    6647       52020 :     const int iStyleFieldIndex = GetFieldIndex("OGR_STYLE");
    6648       52020 :     if (iStyleFieldIndex >= 0)
    6649          62 :         return GetFieldAsString(iStyleFieldIndex);
    6650             : 
    6651       51958 :     return nullptr;
    6652             : }
    6653             : 
    6654             : /************************************************************************/
    6655             : /*                        OGR_F_GetStyleString()                        */
    6656             : /************************************************************************/
    6657             : 
    6658             : /**
    6659             :  * \brief Fetch style string for this feature.
    6660             :  *
    6661             :  * Set the OGR Feature Style Specification for details on the format of
    6662             :  * this string, and ogr_featurestyle.h for services available to parse it.
    6663             :  *
    6664             :  * This function is the same as the C++ method OGRFeature::GetStyleString().
    6665             :  *
    6666             :  * @param hFeat handle to the feature to get the style from.
    6667             :  * @return a reference to a representation in string format, or NULL if
    6668             :  * there isn't one.
    6669             :  */
    6670             : 
    6671        1585 : const char *OGR_F_GetStyleString(OGRFeatureH hFeat)
    6672             : {
    6673        1585 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetStyleString", nullptr);
    6674             : 
    6675        1585 :     return OGRFeature::FromHandle(hFeat)->GetStyleString();
    6676             : }
    6677             : 
    6678             : /************************************************************************/
    6679             : /*                             SetStyleString()                         */
    6680             : /************************************************************************/
    6681             : 
    6682             : /**
    6683             :  * \brief Set feature style string.
    6684             :  *
    6685             :  * This method operates the same as OGRFeature::SetStyleStringDirectly() except
    6686             :  * that it does not assume ownership of the passed string, but instead makes a
    6687             :  * copy of it.
    6688             :  *
    6689             :  * This method is the same as the C function OGR_F_SetStyleString().
    6690             :  *
    6691             :  * @param pszString the style string to apply to this feature, cannot be NULL.
    6692             :  */
    6693             : 
    6694      338631 : void OGRFeature::SetStyleString(const char *pszString)
    6695             : {
    6696      338631 :     if (m_pszStyleString)
    6697             :     {
    6698        2364 :         CPLFree(m_pszStyleString);
    6699        2364 :         m_pszStyleString = nullptr;
    6700             :     }
    6701             : 
    6702      338631 :     if (pszString)
    6703      324475 :         m_pszStyleString = VSI_STRDUP_VERBOSE(pszString);
    6704      338631 : }
    6705             : 
    6706             : /************************************************************************/
    6707             : /*                        OGR_F_SetStyleString()                        */
    6708             : /************************************************************************/
    6709             : 
    6710             : /**
    6711             :  * \brief Set feature style string.
    6712             :  *
    6713             :  * This method operates the same as OGR_F_SetStyleStringDirectly() except that it
    6714             :  * does not assume ownership of the passed string, but instead makes a copy of
    6715             :  * it.
    6716             :  *
    6717             :  * This function is the same as the C++ method OGRFeature::SetStyleString().
    6718             :  *
    6719             :  * @param hFeat handle to the feature to set style to.
    6720             :  * @param pszStyle the style string to apply to this feature, cannot be NULL.
    6721             :  */
    6722             : 
    6723          89 : void OGR_F_SetStyleString(OGRFeatureH hFeat, const char *pszStyle)
    6724             : 
    6725             : {
    6726          89 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleString");
    6727             : 
    6728          89 :     OGRFeature::FromHandle(hFeat)->SetStyleString(pszStyle);
    6729             : }
    6730             : 
    6731             : /************************************************************************/
    6732             : /*                       SetStyleStringDirectly()                       */
    6733             : /************************************************************************/
    6734             : 
    6735             : /**
    6736             :  * \brief Set feature style string.
    6737             :  *
    6738             :  * This method operates the same as OGRFeature::SetStyleString() except that it
    6739             :  * assumes ownership of the passed string.
    6740             :  *
    6741             :  * This method is the same as the C function OGR_F_SetStyleStringDirectly().
    6742             :  *
    6743             :  * @param pszString the style string to apply to this feature, cannot be NULL.
    6744             :  */
    6745             : 
    6746           0 : void OGRFeature::SetStyleStringDirectly(char *pszString)
    6747             : {
    6748           0 :     CPLFree(m_pszStyleString);
    6749           0 :     m_pszStyleString = pszString;
    6750           0 : }
    6751             : 
    6752             : /************************************************************************/
    6753             : /*                     OGR_F_SetStyleStringDirectly()                   */
    6754             : /************************************************************************/
    6755             : 
    6756             : /**
    6757             :  * \brief Set feature style string.
    6758             :  *
    6759             :  * This method operates the same as OGR_F_SetStyleString() except that it assumes
    6760             :  * ownership of the passed string.
    6761             :  *
    6762             :  * This function is the same as the C++ method
    6763             :  * OGRFeature::SetStyleStringDirectly().
    6764             :  *
    6765             :  * @param hFeat handle to the feature to set style to.
    6766             :  * @param pszStyle the style string to apply to this feature, cannot be NULL.
    6767             :  */
    6768             : 
    6769           0 : void OGR_F_SetStyleStringDirectly(OGRFeatureH hFeat, char *pszStyle)
    6770             : 
    6771             : {
    6772           0 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleStringDirectly");
    6773             : 
    6774           0 :     OGRFeature::FromHandle(hFeat)->SetStyleStringDirectly(pszStyle);
    6775             : }
    6776             : 
    6777             : //************************************************************************/
    6778             : /*                           SetStyleTable()                            */
    6779             : /************************************************************************/
    6780             : 
    6781             : /** Set style table.
    6782             :  * @param poStyleTable new style table (will be cloned)
    6783             :  */
    6784           0 : void OGRFeature::SetStyleTable(OGRStyleTable *poStyleTable)
    6785             : {
    6786           0 :     if (m_poStyleTable)
    6787           0 :         delete m_poStyleTable;
    6788           0 :     m_poStyleTable = poStyleTable ? poStyleTable->Clone() : nullptr;
    6789           0 : }
    6790             : 
    6791             : //************************************************************************/
    6792             : /*                          SetStyleTableDirectly()                      */
    6793             : /************************************************************************/
    6794             : 
    6795             : /** Set style table.
    6796             :  * @param poStyleTable new style table (ownership transferred to the object)
    6797             :  */
    6798           0 : void OGRFeature::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
    6799             : {
    6800           0 :     if (m_poStyleTable)
    6801           0 :         delete m_poStyleTable;
    6802           0 :     m_poStyleTable = poStyleTable;
    6803           0 : }
    6804             : 
    6805             : //! @cond Doxygen_Suppress
    6806             : 
    6807             : /************************************************************************/
    6808             : /*                            RemapFields()                             */
    6809             : /*                                                                      */
    6810             : /*      This is used to transform a feature "in place" from one         */
    6811             : /*      feature defn to another with minimum work.                      */
    6812             : /************************************************************************/
    6813             : 
    6814          50 : OGRErr OGRFeature::RemapFields(const OGRFeatureDefn *poNewDefn,
    6815             :                                const int *panRemapSource)
    6816             : 
    6817             : {
    6818          50 :     if (poNewDefn == nullptr)
    6819          50 :         poNewDefn = poDefn;
    6820             : 
    6821          50 :     const int nNewFieldCount = poNewDefn->GetFieldCount();
    6822             :     OGRField *pauNewFields =
    6823          50 :         static_cast<OGRField *>(CPLCalloc(nNewFieldCount, sizeof(OGRField)));
    6824             : 
    6825          50 :     const int nFieldCount = poDefn->GetFieldCount();
    6826         318 :     for (int iDstField = 0; iDstField < nFieldCount; iDstField++)
    6827             :     {
    6828         268 :         if (panRemapSource[iDstField] == -1)
    6829             :         {
    6830          16 :             OGR_RawField_SetUnset(&pauNewFields[iDstField]);
    6831             :         }
    6832             :         else
    6833             :         {
    6834         252 :             memcpy(pauNewFields + iDstField,
    6835         252 :                    pauFields + panRemapSource[iDstField], sizeof(OGRField));
    6836             :         }
    6837             :     }
    6838             : 
    6839             :     // We really should be freeing memory for old columns that
    6840             :     // are no longer present.  We don't for now because it is a bit messy
    6841             :     // and would take too long to test.
    6842             : 
    6843             :     /* -------------------------------------------------------------------- */
    6844             :     /*      Apply new definition and fields.                                */
    6845             :     /* -------------------------------------------------------------------- */
    6846          50 :     CPLFree(pauFields);
    6847          50 :     pauFields = pauNewFields;
    6848             : 
    6849          50 :     poDefn = poNewDefn;
    6850             : 
    6851          50 :     return OGRERR_NONE;
    6852             : }
    6853             : 
    6854             : /************************************************************************/
    6855             : /*                            AppendField()                             */
    6856             : /*                                                                      */
    6857             : /*      This is used to transform a feature "in place" by appending     */
    6858             : /*      an unset field.                                                 */
    6859             : /************************************************************************/
    6860             : 
    6861         573 : void OGRFeature::AppendField()
    6862             : {
    6863         573 :     const int nFieldCount = poDefn->GetFieldCountUnsafe();
    6864         573 :     pauFields = static_cast<OGRField *>(
    6865         573 :         CPLRealloc(pauFields, nFieldCount * sizeof(OGRField)));
    6866         573 :     OGR_RawField_SetUnset(&pauFields[nFieldCount - 1]);
    6867         573 : }
    6868             : 
    6869             : /************************************************************************/
    6870             : /*                        RemapGeomFields()                             */
    6871             : /*                                                                      */
    6872             : /*      This is used to transform a feature "in place" from one         */
    6873             : /*      feature defn to another with minimum work.                      */
    6874             : /************************************************************************/
    6875             : 
    6876           3 : OGRErr OGRFeature::RemapGeomFields(const OGRFeatureDefn *poNewDefn,
    6877             :                                    const int *panRemapSource)
    6878             : 
    6879             : {
    6880           3 :     if (poNewDefn == nullptr)
    6881           3 :         poNewDefn = poDefn;
    6882             : 
    6883             :     OGRGeometry **papoNewGeomFields = static_cast<OGRGeometry **>(
    6884           3 :         CPLCalloc(poNewDefn->GetGeomFieldCount(), sizeof(OGRGeometry *)));
    6885             : 
    6886           9 :     for (int iDstField = 0; iDstField < poDefn->GetGeomFieldCount();
    6887             :          iDstField++)
    6888             :     {
    6889           6 :         if (panRemapSource[iDstField] == -1)
    6890             :         {
    6891           3 :             papoNewGeomFields[iDstField] = nullptr;
    6892             :         }
    6893             :         else
    6894             :         {
    6895           3 :             papoNewGeomFields[iDstField] =
    6896           3 :                 papoGeometries[panRemapSource[iDstField]];
    6897             :         }
    6898             :     }
    6899             : 
    6900             :     // We really should be freeing memory for old columns that
    6901             :     // are no longer present.  We don't for now because it is a bit messy
    6902             :     // and would take too long to test.
    6903             : 
    6904             :     /* -------------------------------------------------------------------- */
    6905             :     /*      Apply new definition and fields.                                */
    6906             :     /* -------------------------------------------------------------------- */
    6907           3 :     CPLFree(papoGeometries);
    6908           3 :     papoGeometries = papoNewGeomFields;
    6909             : 
    6910           3 :     poDefn = poNewDefn;
    6911             : 
    6912           3 :     return OGRERR_NONE;
    6913             : }
    6914             : 
    6915             : //! @endcond
    6916             : 
    6917             : /************************************************************************/
    6918             : /*                         OGR_F_GetStyleTable()                        */
    6919             : /************************************************************************/
    6920             : 
    6921           0 : OGRStyleTableH OGR_F_GetStyleTable(OGRFeatureH hFeat)
    6922             : 
    6923             : {
    6924           0 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetStyleTable", nullptr);
    6925             : 
    6926             :     return reinterpret_cast<OGRStyleTableH>(
    6927           0 :         OGRFeature::FromHandle(hFeat)->GetStyleTable());
    6928             : }
    6929             : 
    6930             : /************************************************************************/
    6931             : /*                         OGR_F_SetStyleTableDirectly()                */
    6932             : /************************************************************************/
    6933             : 
    6934           0 : void OGR_F_SetStyleTableDirectly(OGRFeatureH hFeat, OGRStyleTableH hStyleTable)
    6935             : 
    6936             : {
    6937           0 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleTableDirectly");
    6938             : 
    6939           0 :     OGRFeature::FromHandle(hFeat)->SetStyleTableDirectly(
    6940           0 :         reinterpret_cast<OGRStyleTable *>(hStyleTable));
    6941             : }
    6942             : 
    6943             : /************************************************************************/
    6944             : /*                         OGR_F_SetStyleTable()                        */
    6945             : /************************************************************************/
    6946             : 
    6947           0 : void OGR_F_SetStyleTable(OGRFeatureH hFeat, OGRStyleTableH hStyleTable)
    6948             : 
    6949             : {
    6950           0 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleTable");
    6951           0 :     VALIDATE_POINTER0(hStyleTable, "OGR_F_SetStyleTable");
    6952             : 
    6953           0 :     OGRFeature::FromHandle(hFeat)->SetStyleTable(
    6954           0 :         reinterpret_cast<OGRStyleTable *>(hStyleTable));
    6955             : }
    6956             : 
    6957             : /************************************************************************/
    6958             : /*                          FillUnsetWithDefault()                      */
    6959             : /************************************************************************/
    6960             : 
    6961             : /**
    6962             :  * \brief Fill unset fields with default values that might be defined.
    6963             :  *
    6964             :  * This method is the same as the C function OGR_F_FillUnsetWithDefault().
    6965             :  *
    6966             :  * @param bNotNullableOnly if we should fill only unset fields with a not-null
    6967             :  *                     constraint.
    6968             :  * @param papszOptions unused currently. Must be set to NULL.
    6969             :  */
    6970             : 
    6971      277440 : void OGRFeature::FillUnsetWithDefault(int bNotNullableOnly,
    6972             :                                       CPL_UNUSED char **papszOptions)
    6973             : {
    6974      277440 :     const int nFieldCount = poDefn->GetFieldCount();
    6975     4755510 :     for (int i = 0; i < nFieldCount; i++)
    6976             :     {
    6977     4478070 :         if (IsFieldSetUnsafe(i))
    6978     4476520 :             continue;
    6979        1541 :         const auto poFieldDefn = poDefn->GetFieldDefn(i);
    6980        1541 :         if (bNotNullableOnly && poFieldDefn->IsNullable())
    6981         109 :             continue;
    6982        1432 :         const char *pszDefault = poFieldDefn->GetDefault();
    6983        1432 :         OGRFieldType eType = poFieldDefn->GetType();
    6984        1432 :         if (pszDefault != nullptr)
    6985             :         {
    6986          48 :             if (eType == OFTDate || eType == OFTTime || eType == OFTDateTime)
    6987             :             {
    6988           9 :                 if (STARTS_WITH_CI(pszDefault, "CURRENT"))
    6989             :                 {
    6990           4 :                     time_t t = time(nullptr);
    6991             :                     struct tm brokendown;
    6992           4 :                     CPLUnixTimeToYMDHMS(t, &brokendown);
    6993           4 :                     SetField(i, brokendown.tm_year + 1900,
    6994           4 :                              brokendown.tm_mon + 1, brokendown.tm_mday,
    6995             :                              brokendown.tm_hour, brokendown.tm_min,
    6996           4 :                              static_cast<float>(brokendown.tm_sec), 100);
    6997             :                 }
    6998             :                 else
    6999             :                 {
    7000           5 :                     int nYear = 0;
    7001           5 :                     int nMonth = 0;
    7002           5 :                     int nDay = 0;
    7003           5 :                     int nHour = 0;
    7004           5 :                     int nMinute = 0;
    7005           5 :                     float fSecond = 0.0f;
    7006           5 :                     if (sscanf(pszDefault, "'%d/%d/%d %d:%d:%f'", &nYear,
    7007           5 :                                &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6)
    7008             :                     {
    7009           4 :                         SetField(i, nYear, nMonth, nDay, nHour, nMinute,
    7010             :                                  fSecond, 100);
    7011             :                     }
    7012           9 :                 }
    7013             :             }
    7014          39 :             else if (eType == OFTString && pszDefault[0] == '\'' &&
    7015           8 :                      pszDefault[strlen(pszDefault) - 1] == '\'')
    7016             :             {
    7017          16 :                 CPLString osDefault(pszDefault + 1);
    7018           8 :                 osDefault.pop_back();
    7019           8 :                 char *pszTmp = CPLUnescapeString(osDefault, nullptr, CPLES_SQL);
    7020           8 :                 SetField(i, pszTmp);
    7021          16 :                 CPLFree(pszTmp);
    7022             :             }
    7023          31 :             else if (!poFieldDefn->IsDefaultDriverSpecific())
    7024          13 :                 SetField(i, pszDefault);
    7025             :         }
    7026             :     }
    7027      277440 : }
    7028             : 
    7029             : /************************************************************************/
    7030             : /*                     OGR_F_FillUnsetWithDefault()                     */
    7031             : /************************************************************************/
    7032             : 
    7033             : /**
    7034             :  * \brief Fill unset fields with default values that might be defined.
    7035             :  *
    7036             :  * This function is the same as the C++ method
    7037             :  * OGRFeature::FillUnsetWithDefault().
    7038             :  *
    7039             :  * @param hFeat handle to the feature.
    7040             :  * @param bNotNullableOnly if we should fill only unset fields with a not-null
    7041             :  *                     constraint.
    7042             :  * @param papszOptions unused currently. Must be set to NULL.
    7043             :  */
    7044             : 
    7045           2 : void OGR_F_FillUnsetWithDefault(OGRFeatureH hFeat, int bNotNullableOnly,
    7046             :                                 char **papszOptions)
    7047             : 
    7048             : {
    7049           2 :     VALIDATE_POINTER0(hFeat, "OGR_F_FillUnsetWithDefault");
    7050             : 
    7051           2 :     OGRFeature::FromHandle(hFeat)->FillUnsetWithDefault(bNotNullableOnly,
    7052             :                                                         papszOptions);
    7053             : }
    7054             : 
    7055             : /************************************************************************/
    7056             : /*                              Validate()                              */
    7057             : /************************************************************************/
    7058             : 
    7059             : /**
    7060             :  * \brief Validate that a feature meets constraints of its schema.
    7061             :  *
    7062             :  * The scope of test is specified with the nValidateFlags parameter.
    7063             :  *
    7064             :  * Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width must be
    7065             :  * interpreted as the number of UTF-8 characters. Some drivers might interpret
    7066             :  * the width as the number of bytes instead. So this test is rather conservative
    7067             :  * (if it fails, then it will fail for all interpretations).
    7068             :  *
    7069             :  * This method is the same as the C function OGR_F_Validate().
    7070             :  *
    7071             :  * @param nValidateFlags OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
    7072             :  *                       OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and
    7073             :  *                       OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT,
    7074             :  *                       OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM with '|' operator
    7075             :  * @param bEmitError TRUE if a CPLError() must be emitted when a check fails
    7076             :  * @return TRUE if all enabled validation tests pass.
    7077             :  */
    7078             : 
    7079         470 : int OGRFeature::Validate(int nValidateFlags, int bEmitError) const
    7080             : 
    7081             : {
    7082         470 :     bool bRet = true;
    7083             : 
    7084         470 :     const int nGeomFieldCount = poDefn->GetGeomFieldCount();
    7085         900 :     for (int i = 0; i < nGeomFieldCount; i++)
    7086             :     {
    7087         430 :         if ((nValidateFlags & OGR_F_VAL_NULL) &&
    7088         860 :             !poDefn->GetGeomFieldDefn(i)->IsNullable() &&
    7089          12 :             GetGeomFieldRef(i) == nullptr)
    7090             :         {
    7091           3 :             bRet = false;
    7092           3 :             if (bEmitError)
    7093             :             {
    7094           3 :                 CPLError(
    7095             :                     CE_Failure, CPLE_AppDefined,
    7096             :                     "Geometry field %s has a NULL content which is not allowed",
    7097           3 :                     poDefn->GetGeomFieldDefn(i)->GetNameRef());
    7098             :             }
    7099             :         }
    7100         603 :         if ((nValidateFlags & OGR_F_VAL_GEOM_TYPE) &&
    7101         173 :             poDefn->GetGeomFieldDefn(i)->GetType() != wkbUnknown)
    7102             :         {
    7103         136 :             const OGRGeometry *poGeom = GetGeomFieldRef(i);
    7104         136 :             if (poGeom != nullptr)
    7105             :             {
    7106             :                 const OGRwkbGeometryType eType =
    7107         101 :                     poDefn->GetGeomFieldDefn(i)->GetType();
    7108         101 :                 const OGRwkbGeometryType eFType = poGeom->getGeometryType();
    7109         200 :                 if ((nValidateFlags & OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM) &&
    7110          99 :                     (wkbFlatten(eFType) == wkbFlatten(eType) ||
    7111          17 :                      wkbFlatten(eType) == wkbUnknown))
    7112             :                 {
    7113             :                     // Ok.
    7114             :                 }
    7115          32 :                 else if ((eType == wkbSetZ(wkbUnknown) && !wkbHasZ(eFType)) ||
    7116          16 :                          (eType != wkbSetZ(wkbUnknown) && eFType != eType))
    7117             :                 {
    7118          15 :                     bRet = false;
    7119          15 :                     if (bEmitError)
    7120             :                     {
    7121          30 :                         CPLError(CE_Failure, CPLE_AppDefined,
    7122             :                                  "Geometry field %s has a %s geometry whereas "
    7123             :                                  "%s is expected",
    7124          15 :                                  poDefn->GetGeomFieldDefn(i)->GetNameRef(),
    7125             :                                  OGRGeometryTypeToName(eFType),
    7126             :                                  OGRGeometryTypeToName(eType));
    7127             :                     }
    7128             :                 }
    7129             :             }
    7130             :         }
    7131             :     }
    7132         470 :     const int nFieldCount = poDefn->GetFieldCount();
    7133        1670 :     for (int i = 0; i < nFieldCount; i++)
    7134             :     {
    7135        1200 :         if ((nValidateFlags & OGR_F_VAL_NULL) &&
    7136        2403 :             !poDefn->GetFieldDefn(i)->IsNullable() && !IsFieldSet(i) &&
    7137           3 :             (!(nValidateFlags & OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT) ||
    7138           2 :              poDefn->GetFieldDefn(i)->GetDefault() == nullptr))
    7139             :         {
    7140           3 :             bRet = false;
    7141           3 :             if (bEmitError)
    7142             :             {
    7143           6 :                 CPLError(CE_Failure, CPLE_AppDefined,
    7144             :                          "Field %s.%s has a NULL content which is not allowed",
    7145           3 :                          poDefn->GetName(),
    7146           3 :                          poDefn->GetFieldDefn(i)->GetNameRef());
    7147             :             }
    7148             :         }
    7149         630 :         if ((nValidateFlags & OGR_F_VAL_WIDTH) &&
    7150         866 :             poDefn->GetFieldDefn(i)->GetWidth() > 0 &&
    7151         308 :             poDefn->GetFieldDefn(i)->GetType() == OFTString && IsFieldSet(i) &&
    7152        1902 :             CPLIsUTF8(GetFieldAsString(i), -1) &&
    7153          72 :             CPLStrlenUTF8Ex(GetFieldAsString(i)) >
    7154          72 :                 static_cast<size_t>(poDefn->GetFieldDefn(i)->GetWidth()))
    7155             :         {
    7156           1 :             bRet = false;
    7157           1 :             if (bEmitError)
    7158             :             {
    7159           3 :                 CPLError(
    7160             :                     CE_Failure, CPLE_AppDefined,
    7161             :                     "Field %s.%s has %" PRIu64 " UTF-8 characters whereas "
    7162             :                     "a maximum of %d is allowed",
    7163           1 :                     poDefn->GetName(), poDefn->GetFieldDefn(i)->GetNameRef(),
    7164           1 :                     static_cast<uint64_t>(CPLStrlenUTF8Ex(GetFieldAsString(i))),
    7165           1 :                     poDefn->GetFieldDefn(i)->GetWidth());
    7166             :             }
    7167             :         }
    7168             :     }
    7169             : 
    7170         470 :     return bRet;
    7171             : }
    7172             : 
    7173             : /************************************************************************/
    7174             : /*                           OGR_F_Validate()                           */
    7175             : /************************************************************************/
    7176             : 
    7177             : /**
    7178             :  * \brief Validate that a feature meets constraints of its schema.
    7179             :  *
    7180             :  * The scope of test is specified with the nValidateFlags parameter.
    7181             :  *
    7182             :  * Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width must be
    7183             :  * interpreted as the number of UTF-8 characters. Some drivers might interpret
    7184             :  * the width as the number of bytes instead. So this test is rather conservative
    7185             :  * (if it fails, then it will fail for all interpretations).
    7186             :  *
    7187             :  * This function is the same as the C++ method
    7188             :  * OGRFeature::Validate().
    7189             :  *
    7190             :  * @param hFeat handle to the feature to validate.
    7191             :  * @param nValidateFlags OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
    7192             :  *                       OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and
    7193             :  *                       OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT with '|' operator
    7194             :  * @param bEmitError TRUE if a CPLError() must be emitted when a check fails
    7195             :  * @return TRUE if all enabled validation tests pass.
    7196             :  */
    7197             : 
    7198          10 : int OGR_F_Validate(OGRFeatureH hFeat, int nValidateFlags, int bEmitError)
    7199             : 
    7200             : {
    7201          10 :     VALIDATE_POINTER1(hFeat, "OGR_F_Validate", FALSE);
    7202             : 
    7203          10 :     return OGRFeature::FromHandle(hFeat)->Validate(nValidateFlags, bEmitError);
    7204             : }
    7205             : 
    7206             : /************************************************************************/
    7207             : /*                          GetNativeData()                             */
    7208             : /************************************************************************/
    7209             : 
    7210             : /**
    7211             :  * \fn const char* OGRFeature::GetNativeData() const;
    7212             :  *
    7213             :  * \brief Returns the native data for the feature.
    7214             :  *
    7215             :  * The native data is the representation in a "natural" form that comes from
    7216             :  * the driver that created this feature, or that is aimed at an output driver.
    7217             :  * The native data may be in different format, which is indicated by
    7218             :  * GetNativeMediaType().
    7219             :  *
    7220             :  * Note that most drivers do not support storing the native data in the feature
    7221             :  * object, and if they do, generally the NATIVE_DATA open option must be passed
    7222             :  * at dataset opening.
    7223             :  *
    7224             :  * The "native data" does not imply it is something more performant or powerful
    7225             :  * than what can be obtained with the rest of the API, but it may be useful in
    7226             :  * round-tripping scenarios where some characteristics of the underlying format
    7227             :  * are not captured otherwise by the OGR abstraction.
    7228             :  *
    7229             :  * This function is the same as the C function
    7230             :  * OGR_F_GetNativeData().
    7231             :  *
    7232             :  * @return a string with the native data, or NULL if there is none.
    7233             :  *
    7234             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7235             :  */
    7236             : 
    7237             : /************************************************************************/
    7238             : /*                         OGR_F_GetNativeData()                        */
    7239             : /************************************************************************/
    7240             : 
    7241             : /**
    7242             :  * \brief Returns the native data for the feature.
    7243             :  *
    7244             :  * The native data is the representation in a "natural" form that comes from
    7245             :  * the driver that created this feature, or that is aimed at an output driver.
    7246             :  * The native data may be in different format, which is indicated by
    7247             :  * OGR_F_GetNativeMediaType().
    7248             :  *
    7249             :  * Note that most drivers do not support storing the native data in the feature
    7250             :  * object, and if they do, generally the NATIVE_DATA open option must be passed
    7251             :  * at dataset opening.
    7252             :  *
    7253             :  * The "native data" does not imply it is something more performant or powerful
    7254             :  * than what can be obtained with the rest of the API, but it may be useful in
    7255             :  * round-tripping scenarios where some characteristics of the underlying format
    7256             :  * are not captured otherwise by the OGR abstraction.
    7257             :  *
    7258             :  * This function is the same as the C++ method
    7259             :  * OGRFeature::GetNativeData().
    7260             :  *
    7261             :  * @param hFeat handle to the feature.
    7262             :  * @return a string with the native data, or NULL if there is none.
    7263             :  *
    7264             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7265             :  */
    7266             : 
    7267           9 : const char *OGR_F_GetNativeData(OGRFeatureH hFeat)
    7268             : 
    7269             : {
    7270           9 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetNativeData", nullptr);
    7271             : 
    7272           9 :     return OGRFeature::FromHandle(hFeat)->GetNativeData();
    7273             : }
    7274             : 
    7275             : /************************************************************************/
    7276             : /*                        GetNativeMediaType()                          */
    7277             : /************************************************************************/
    7278             : 
    7279             : /**
    7280             :  * \fn const char* OGRFeature::GetNativeMediaType() const;
    7281             :  *
    7282             :  * \brief Returns the native media type for the feature.
    7283             :  *
    7284             :  * The native media type is the identifier for the format of the native data.
    7285             :  * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
    7286             :  * e.g. "application/vnd.geo+json" for JSon.
    7287             :  *
    7288             :  * This function is the same as the C function
    7289             :  * OGR_F_GetNativeMediaType().
    7290             :  *
    7291             :  * @return a string with the native media type, or NULL if there is none.
    7292             :  *
    7293             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7294             :  */
    7295             : 
    7296             : /************************************************************************/
    7297             : /*                       OGR_F_GetNativeMediaType()                     */
    7298             : /************************************************************************/
    7299             : 
    7300             : /**
    7301             :  * \brief Returns the native media type for the feature.
    7302             :  *
    7303             :  * The native media type is the identifier for the format of the native data.
    7304             :  * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
    7305             :  * e.g. "application/vnd.geo+json" for JSon.
    7306             :  *
    7307             :  * This function is the same as the C function
    7308             :  * OGR_F_GetNativeMediaType().
    7309             :  *
    7310             :  * @param hFeat handle to the feature.
    7311             :  * @return a string with the native media type, or NULL if there is none.
    7312             :  *
    7313             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7314             :  */
    7315             : 
    7316           9 : const char *OGR_F_GetNativeMediaType(OGRFeatureH hFeat)
    7317             : {
    7318           9 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetNativeMediaType", nullptr);
    7319             : 
    7320           9 :     return OGRFeature::FromHandle(hFeat)->GetNativeMediaType();
    7321             : }
    7322             : 
    7323             : /************************************************************************/
    7324             : /*                           SetNativeData()                            */
    7325             : /************************************************************************/
    7326             : 
    7327             : /**
    7328             :  * \brief Sets the native data for the feature.
    7329             :  *
    7330             :  * The native data is the representation in a "natural" form that comes from
    7331             :  * the driver that created this feature, or that is aimed at an output driver.
    7332             :  * The native data may be in different format, which is indicated by
    7333             :  * GetNativeMediaType().
    7334             :  *
    7335             :  * This function is the same as the C function
    7336             :  * OGR_F_SetNativeData().
    7337             :  *
    7338             :  * @param pszNativeData a string with the native data, or NULL if there is none.
    7339             :  *
    7340             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7341             :  */
    7342             : 
    7343       14554 : void OGRFeature::SetNativeData(const char *pszNativeData)
    7344             : {
    7345       14554 :     CPLFree(m_pszNativeData);
    7346       14554 :     m_pszNativeData =
    7347       14554 :         pszNativeData ? VSI_STRDUP_VERBOSE(pszNativeData) : nullptr;
    7348       14554 : }
    7349             : 
    7350             : /************************************************************************/
    7351             : /*                          OGR_F_SetNativeData()                       */
    7352             : /************************************************************************/
    7353             : 
    7354             : /**
    7355             :  * \brief Sets the native data for the feature.
    7356             :  *
    7357             :  * The native data is the representation in a "natural" form that comes from
    7358             :  * the driver that created this feature, or that is aimed at an output driver.
    7359             :  * The native data may be in different format, which is indicated by
    7360             :  * OGR_F_GetNativeMediaType().
    7361             :  *
    7362             :  * This function is the same as the C++ method
    7363             :  * OGRFeature::SetNativeData().
    7364             :  *
    7365             :  * @param hFeat handle to the feature.
    7366             :  * @param pszNativeData a string with the native data, or NULL if there is none.
    7367             :  *
    7368             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7369             :  */
    7370             : 
    7371           4 : void OGR_F_SetNativeData(OGRFeatureH hFeat, const char *pszNativeData)
    7372             : {
    7373           4 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetNativeData");
    7374             : 
    7375           4 :     OGRFeature::FromHandle(hFeat)->SetNativeData(pszNativeData);
    7376             : }
    7377             : 
    7378             : /************************************************************************/
    7379             : /*                         SetNativeMediaType()                         */
    7380             : /************************************************************************/
    7381             : 
    7382             : /**
    7383             :  * \brief Sets the native media type for the feature.
    7384             :  *
    7385             :  * The native media type is the identifier for the format of the native data.
    7386             :  * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
    7387             :  * e.g. "application/vnd.geo+json" for JSon.
    7388             :  *
    7389             :  * This function is the same as the C function
    7390             :  * OGR_F_SetNativeMediaType().
    7391             :  *
    7392             :  * @param pszNativeMediaType a string with the native media type, or NULL if
    7393             :  * there is none.
    7394             :  *
    7395             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7396             :  */
    7397             : 
    7398       14554 : void OGRFeature::SetNativeMediaType(const char *pszNativeMediaType)
    7399             : {
    7400       14554 :     CPLFree(m_pszNativeMediaType);
    7401       14554 :     m_pszNativeMediaType =
    7402       14554 :         pszNativeMediaType ? VSI_STRDUP_VERBOSE(pszNativeMediaType) : nullptr;
    7403       14554 : }
    7404             : 
    7405             : /************************************************************************/
    7406             : /*                          OGR_F_SetNativeMediaType()                  */
    7407             : /************************************************************************/
    7408             : 
    7409             : /**
    7410             :  * \brief Sets the native media type for the feature.
    7411             :  *
    7412             :  * The native media type is the identifier for the format of the native data.
    7413             :  * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
    7414             :  * e.g. "application/vnd.geo+json" for JSon.
    7415             :  *
    7416             :  * This function is the same as the C++ method
    7417             :  * OGRFeature::SetNativeMediaType().
    7418             :  *
    7419             :  * @param hFeat handle to the feature.
    7420             :  * @param pszNativeMediaType a string with the native media type, or NULL if
    7421             :  * there is none.
    7422             :  *
    7423             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7424             :  */
    7425             : 
    7426           4 : void OGR_F_SetNativeMediaType(OGRFeatureH hFeat, const char *pszNativeMediaType)
    7427             : {
    7428           4 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetNativeMediaType");
    7429             : 
    7430           4 :     OGRFeature::FromHandle(hFeat)->SetNativeMediaType(pszNativeMediaType);
    7431             : }
    7432             : 
    7433             : /************************************************************************/
    7434             : /*                           OGR_RawField_IsUnset()                     */
    7435             : /************************************************************************/
    7436             : 
    7437             : /**
    7438             :  * \brief Returns whether a raw field is unset.
    7439             :  *
    7440             :  * Note: this function is rather low-level and should be rarely used in client
    7441             :  * code. Use instead OGR_F_IsFieldSet().
    7442             :  *
    7443             :  * @param puField pointer to raw field.
    7444             :  */
    7445             : 
    7446     3740160 : int OGR_RawField_IsUnset(const OGRField *puField)
    7447             : {
    7448     5174850 :     return puField->Set.nMarker1 == OGRUnsetMarker &&
    7449     5174850 :            puField->Set.nMarker2 == OGRUnsetMarker &&
    7450     5174850 :            puField->Set.nMarker3 == OGRUnsetMarker;
    7451             : }
    7452             : 
    7453             : /************************************************************************/
    7454             : /*                           OGR_RawField_IsNull()                      */
    7455             : /************************************************************************/
    7456             : 
    7457             : /**
    7458             :  * \brief Returns whether a raw field is null.
    7459             :  *
    7460             :  * Note: this function is rather low-level and should be rarely used in client
    7461             :  * code. Use instead OGR_F_IsFieldNull().
    7462             :  *
    7463             :  * @param puField pointer to raw field.
    7464             :  */
    7465             : 
    7466     2291850 : int OGR_RawField_IsNull(const OGRField *puField)
    7467             : {
    7468     2296520 :     return puField->Set.nMarker1 == OGRNullMarker &&
    7469     2296520 :            puField->Set.nMarker2 == OGRNullMarker &&
    7470     2296520 :            puField->Set.nMarker3 == OGRNullMarker;
    7471             : }
    7472             : 
    7473             : /************************************************************************/
    7474             : /*                          OGR_RawField_SetUnset()                     */
    7475             : /************************************************************************/
    7476             : 
    7477             : /**
    7478             :  * \brief Mark a raw field as unset.
    7479             :  *
    7480             :  * This should be called on a un-initialized field. In particular this will not
    7481             :  * free any memory dynamically allocated.
    7482             :  *
    7483             :  * Note: this function is rather low-level and should be rarely used in client
    7484             :  * code. Use instead OGR_F_UnsetField().
    7485             :  *
    7486             :  * @param puField pointer to raw field.
    7487             :  */
    7488             : 
    7489      116049 : void OGR_RawField_SetUnset(OGRField *puField)
    7490             : {
    7491      116049 :     puField->Set.nMarker1 = OGRUnsetMarker;
    7492      116049 :     puField->Set.nMarker2 = OGRUnsetMarker;
    7493      116049 :     puField->Set.nMarker3 = OGRUnsetMarker;
    7494      116049 : }
    7495             : 
    7496             : /************************************************************************/
    7497             : /*                          OGR_RawField_SetNull()                      */
    7498             : /************************************************************************/
    7499             : 
    7500             : /**
    7501             :  * \brief Mark a raw field as null.
    7502             :  *
    7503             :  * This should be called on a un-initialized field. In particular this will not
    7504             :  * free any memory dynamically allocated.
    7505             :  *
    7506             :  * Note: this function is rather low-level and should be rarely used in client
    7507             :  * code. Use instead OGR_F_SetFieldNull().
    7508             :  *
    7509             :  * @param puField pointer to raw field.
    7510             :  */
    7511             : 
    7512       55940 : void OGR_RawField_SetNull(OGRField *puField)
    7513             : {
    7514       55940 :     puField->Set.nMarker1 = OGRNullMarker;
    7515       55940 :     puField->Set.nMarker2 = OGRNullMarker;
    7516       55940 :     puField->Set.nMarker3 = OGRNullMarker;
    7517       55940 : }
    7518             : 
    7519             : /************************************************************************/
    7520             : /*                     OGRFeatureUniquePtrDeleter                       */
    7521             : /************************************************************************/
    7522             : 
    7523             : //! @cond Doxygen_Suppress
    7524      166115 : void OGRFeatureUniquePtrDeleter::operator()(OGRFeature *poFeature) const
    7525             : {
    7526      166115 :     delete poFeature;
    7527      166115 : }
    7528             : 
    7529             : //! @endcond
    7530             : 
    7531             : namespace
    7532             : {
    7533             : // Implementation borrowed to OpenFileGDB
    7534             : 
    7535             : /************************************************************************/
    7536             : /*                            WriteUInt8()                              */
    7537             : /************************************************************************/
    7538             : 
    7539        9817 : inline void WriteUInt8(std::vector<GByte> &abyBuffer, uint8_t nVal)
    7540             : {
    7541        9817 :     abyBuffer.push_back(nVal);
    7542        9817 : }
    7543             : 
    7544             : /************************************************************************/
    7545             : /*                             WriteVarUInt()                           */
    7546             : /************************************************************************/
    7547             : 
    7548        5381 : inline void WriteVarUInt(std::vector<GByte> &abyBuffer, uint64_t nVal)
    7549             : {
    7550             :     while (true)
    7551             :     {
    7552        5381 :         if (nVal >= 0x80)
    7553             :         {
    7554          16 :             WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nVal & 0x7F)));
    7555          16 :             nVal >>= 7;
    7556             :         }
    7557             :         else
    7558             :         {
    7559        5365 :             WriteUInt8(abyBuffer, static_cast<uint8_t>(nVal));
    7560        5365 :             break;
    7561             :         }
    7562             :     }
    7563        5365 : }
    7564             : 
    7565             : /************************************************************************/
    7566             : /*                             WriteVarInt()                            */
    7567             : /************************************************************************/
    7568             : 
    7569        4426 : inline void WriteVarInt(std::vector<GByte> &abyBuffer, int64_t nVal)
    7570             : {
    7571             :     uint64_t nUVal;
    7572        4426 :     if (nVal < 0)
    7573             :     {
    7574           7 :         if (nVal == std::numeric_limits<int64_t>::min())
    7575           0 :             nUVal = static_cast<uint64_t>(1) << 63;
    7576             :         else
    7577           7 :             nUVal = -nVal;
    7578           7 :         if (nUVal >= 0x40)
    7579             :         {
    7580           5 :             WriteUInt8(abyBuffer,
    7581           5 :                        static_cast<uint8_t>(0x80 | 0x40 | (nUVal & 0x3F)));
    7582           5 :             nUVal >>= 6;
    7583             :         }
    7584             :         else
    7585             :         {
    7586           2 :             WriteUInt8(abyBuffer, static_cast<uint8_t>(0x40 | (nUVal & 0x3F)));
    7587           2 :             return;
    7588             :         }
    7589             :     }
    7590             :     else
    7591             :     {
    7592        4419 :         nUVal = nVal;
    7593        4419 :         if (nUVal >= 0x40)
    7594             :         {
    7595        4154 :             WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nUVal & 0x3F)));
    7596        4154 :             nUVal >>= 6;
    7597             :         }
    7598             :         else
    7599             :         {
    7600         265 :             WriteUInt8(abyBuffer, static_cast<uint8_t>((nUVal & 0x3F)));
    7601         265 :             return;
    7602             :         }
    7603             :     }
    7604             : 
    7605        4159 :     WriteVarUInt(abyBuffer, nUVal);
    7606             : }
    7607             : 
    7608             : /************************************************************************/
    7609             : /*                          WriteFloat32()                              */
    7610             : /************************************************************************/
    7611             : 
    7612           2 : inline void WriteFloat32(std::vector<GByte> &abyBuffer, float fVal)
    7613             : {
    7614           2 :     CPL_LSBPTR32(&fVal);
    7615           2 :     const GByte *pabyInput = reinterpret_cast<const GByte *>(&fVal);
    7616           2 :     abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(fVal));
    7617           2 : }
    7618             : 
    7619             : /************************************************************************/
    7620             : /*                          WriteFloat64()                              */
    7621             : /************************************************************************/
    7622             : 
    7623           3 : inline void WriteFloat64(std::vector<GByte> &abyBuffer, double dfVal)
    7624             : {
    7625           3 :     CPL_LSBPTR64(&dfVal);
    7626           3 :     const GByte *pabyInput = reinterpret_cast<const GByte *>(&dfVal);
    7627           3 :     abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(dfVal));
    7628           3 : }
    7629             : 
    7630             : }  // namespace
    7631             : 
    7632             : /************************************************************************/
    7633             : /*                    OGRFeature::SerializeToBinary()                   */
    7634             : /************************************************************************/
    7635             : 
    7636             : /** Serialize the feature to a binary encoding.
    7637             :  *
    7638             :  * This saves the feature ID, attribute fields content and geometry fields
    7639             :  * content.
    7640             :  *
    7641             :  * This method is aimed at being paired with DeserializeFromBinary().
    7642             :  *
    7643             :  * The format of that encoding may vary across GDAL versions.
    7644             :  *
    7645             :  * Note that abyBuffer is cleared at the beginning of this function.
    7646             :  *
    7647             :  * @since 3.9
    7648             :  */
    7649        2209 : bool OGRFeature::SerializeToBinary(std::vector<GByte> &abyBuffer) const
    7650             : {
    7651        2209 :     const int nFieldCount = poDefn->GetFieldCount();
    7652        2209 :     const int nGeomFieldCount = poDefn->GetGeomFieldCount();
    7653             :     try
    7654             :     {
    7655        2209 :         abyBuffer.clear();
    7656             :         // Set field flags
    7657             :         // For attribute fields, we have 2 bits
    7658             :         // - first one set if the field is unset
    7659             :         // - second one set if the field is null
    7660             :         // For geometry fields, we have one bit set to indicate if the geometry
    7661             :         // is non-null.
    7662        2209 :         const size_t nPresenceFlagsSize =
    7663        2209 :             ((2 * nFieldCount + nGeomFieldCount) + 7) / 8;
    7664        2209 :         abyBuffer.resize(nPresenceFlagsSize);
    7665             : 
    7666        2209 :         WriteVarInt(abyBuffer, GetFID());
    7667             : 
    7668        1028 :         const auto SetFlagBit = [&abyBuffer](int iBit)
    7669        1028 :         { abyBuffer[iBit / 8] |= (1 << (iBit % 8)); };
    7670             : 
    7671        4449 :         for (int i = 0; i < nFieldCount; ++i)
    7672             :         {
    7673        2240 :             const OGRField &uField = pauFields[i];
    7674        2240 :             if (OGR_RawField_IsUnset(&uField))
    7675             :             {
    7676          23 :                 const int iBit = 2 * i;
    7677          23 :                 SetFlagBit(iBit);
    7678          23 :                 continue;
    7679             :             }
    7680        2217 :             if (OGR_RawField_IsNull(&uField))
    7681             :             {
    7682           1 :                 const int iBit = 2 * i + 1;
    7683           1 :                 SetFlagBit(iBit);
    7684           1 :                 continue;
    7685             :             }
    7686        2216 :             const auto poFDefn = poDefn->GetFieldDefn(i);
    7687        2216 :             switch (poFDefn->GetType())
    7688             :             {
    7689        2205 :                 case OFTInteger:
    7690             :                 {
    7691        2205 :                     WriteVarInt(abyBuffer, uField.Integer);
    7692        2205 :                     break;
    7693             :                 }
    7694           1 :                 case OFTInteger64:
    7695             :                 {
    7696           1 :                     WriteVarInt(abyBuffer, uField.Integer64);
    7697           1 :                     break;
    7698             :                 }
    7699           1 :                 case OFTReal:
    7700             :                 {
    7701           1 :                     WriteFloat64(abyBuffer, uField.Real);
    7702           1 :                     break;
    7703             :                 }
    7704           1 :                 case OFTString:
    7705             :                 {
    7706           1 :                     const size_t nStrSize = strlen(uField.String);
    7707           1 :                     WriteVarUInt(abyBuffer, nStrSize);
    7708           1 :                     const GByte *pabyStr =
    7709             :                         reinterpret_cast<const GByte *>(uField.String);
    7710           0 :                     abyBuffer.insert(abyBuffer.end(), pabyStr,
    7711           1 :                                      pabyStr + nStrSize);
    7712           1 :                     break;
    7713             :                 }
    7714           1 :                 case OFTIntegerList:
    7715             :                 {
    7716           1 :                     WriteVarInt(abyBuffer, uField.IntegerList.nCount);
    7717           3 :                     for (int j = 0; j < uField.IntegerList.nCount; ++j)
    7718           2 :                         WriteVarInt(abyBuffer, uField.IntegerList.paList[j]);
    7719           1 :                     break;
    7720             :                 }
    7721           1 :                 case OFTInteger64List:
    7722             :                 {
    7723           1 :                     WriteVarInt(abyBuffer, uField.Integer64List.nCount);
    7724           3 :                     for (int j = 0; j < uField.Integer64List.nCount; ++j)
    7725           2 :                         WriteVarInt(abyBuffer, uField.Integer64List.paList[j]);
    7726           1 :                     break;
    7727             :                 }
    7728           1 :                 case OFTRealList:
    7729             :                 {
    7730           1 :                     WriteVarInt(abyBuffer, uField.RealList.nCount);
    7731           3 :                     for (int j = 0; j < uField.RealList.nCount; ++j)
    7732           2 :                         WriteFloat64(abyBuffer, uField.RealList.paList[j]);
    7733           1 :                     break;
    7734             :                 }
    7735           1 :                 case OFTStringList:
    7736             :                 {
    7737           1 :                     WriteVarInt(abyBuffer, uField.StringList.nCount);
    7738           3 :                     for (int j = 0; j < uField.StringList.nCount; ++j)
    7739             :                     {
    7740           2 :                         const char *pszStr = uField.StringList.paList[j];
    7741           2 :                         const size_t nStrSize = strlen(pszStr);
    7742           2 :                         WriteVarUInt(abyBuffer, nStrSize);
    7743           2 :                         const GByte *pabyStr =
    7744             :                             reinterpret_cast<const GByte *>(pszStr);
    7745           0 :                         abyBuffer.insert(abyBuffer.end(), pabyStr,
    7746           2 :                                          pabyStr + nStrSize);
    7747             :                     }
    7748           1 :                     break;
    7749             :                 }
    7750           1 :                 case OFTBinary:
    7751             :                 {
    7752           1 :                     WriteVarInt(abyBuffer, uField.Binary.nCount);
    7753           0 :                     abyBuffer.insert(abyBuffer.end(), uField.Binary.paData,
    7754           1 :                                      uField.Binary.paData +
    7755           1 :                                          uField.Binary.nCount);
    7756           1 :                     break;
    7757             :                 }
    7758           0 :                 case OFTWideString:
    7759             :                 case OFTWideStringList:
    7760           0 :                     break;
    7761           1 :                 case OFTDate:
    7762             :                 {
    7763           1 :                     WriteVarInt(abyBuffer, uField.Date.Year);
    7764           1 :                     WriteUInt8(abyBuffer, uField.Date.Month);
    7765           1 :                     WriteUInt8(abyBuffer, uField.Date.Day);
    7766           1 :                     break;
    7767             :                 }
    7768           1 :                 case OFTTime:
    7769             :                 {
    7770           1 :                     WriteUInt8(abyBuffer, uField.Date.Hour);
    7771           1 :                     WriteUInt8(abyBuffer, uField.Date.Minute);
    7772           1 :                     WriteFloat32(abyBuffer, uField.Date.Second);
    7773           1 :                     WriteUInt8(abyBuffer, uField.Date.TZFlag);
    7774           1 :                     break;
    7775             :                 }
    7776           1 :                 case OFTDateTime:
    7777             :                 {
    7778           1 :                     WriteVarInt(abyBuffer, uField.Date.Year);
    7779           1 :                     WriteUInt8(abyBuffer, uField.Date.Month);
    7780           1 :                     WriteUInt8(abyBuffer, uField.Date.Day);
    7781           1 :                     WriteUInt8(abyBuffer, uField.Date.Hour);
    7782           1 :                     WriteUInt8(abyBuffer, uField.Date.Minute);
    7783           1 :                     WriteFloat32(abyBuffer, uField.Date.Second);
    7784           1 :                     WriteUInt8(abyBuffer, uField.Date.TZFlag);
    7785           1 :                     break;
    7786             :                 }
    7787             :             }
    7788             :         }
    7789        4416 :         for (int i = 0; i < nGeomFieldCount; ++i)
    7790             :         {
    7791        2207 :             if (!papoGeometries[i])
    7792             :             {
    7793        1004 :                 const int iBit = 2 * nFieldCount + i;
    7794        1004 :                 SetFlagBit(iBit);
    7795        1004 :                 continue;
    7796             :             }
    7797        1203 :             const size_t nSize = papoGeometries[i]->WkbSize();
    7798        1203 :             WriteVarUInt(abyBuffer, nSize);
    7799        1203 :             const size_t nBufSizeBefore = abyBuffer.size();
    7800        1203 :             abyBuffer.resize(nBufSizeBefore + nSize);
    7801        1203 :             papoGeometries[i]->exportToWkb(
    7802        1203 :                 wkbNDR, abyBuffer.data() + nBufSizeBefore, wkbVariantIso);
    7803             :         }
    7804        2209 :         return true;
    7805             :     }
    7806           0 :     catch (const std::bad_alloc &)
    7807             :     {
    7808           0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
    7809           0 :         return false;
    7810             :     }
    7811             : }
    7812             : 
    7813             : namespace
    7814             : {
    7815             : // Implementation borrowed to OpenFileGDB
    7816             : 
    7817             : /************************************************************************/
    7818             : /*                          ReadVarUInt()                               */
    7819             : /************************************************************************/
    7820             : 
    7821             : template <class OutType>
    7822        1805 : static bool ReadVarUInt(const GByte *&pabyIter, const GByte *pabyEnd,
    7823             :                         OutType &nOutVal)
    7824             : {
    7825        1805 :     if (pabyIter >= pabyEnd)
    7826           3 :         return false;
    7827        1802 :     OutType b = *pabyIter;
    7828        1802 :     if ((b & 0x80) == 0)
    7829             :     {
    7830        1797 :         pabyIter++;
    7831        1797 :         nOutVal = b;
    7832        1797 :         return true;
    7833             :     }
    7834           5 :     const GByte *pabyLocalIter = pabyIter + 1;
    7835           5 :     int nShift = 7;
    7836           5 :     OutType nVal = (b & 0x7F);
    7837             :     while (true)
    7838             :     {
    7839           5 :         if (pabyLocalIter >= pabyEnd)
    7840           0 :             return false;
    7841           5 :         b = *pabyLocalIter;
    7842           5 :         pabyLocalIter++;
    7843           5 :         nVal |= (b & 0x7F) << nShift;
    7844           5 :         if ((b & 0x80) == 0)
    7845             :         {
    7846           5 :             pabyIter = pabyLocalIter;
    7847           5 :             nOutVal = nVal;
    7848           5 :             return true;
    7849             :         }
    7850           0 :         nShift += 7;
    7851             :         // To avoid undefined behavior later when doing << nShift
    7852           0 :         if (nShift >= static_cast<int>(sizeof(OutType)) * 8)
    7853             :         {
    7854           0 :             return false;
    7855             :         }
    7856             :     }
    7857             : }
    7858             : 
    7859             : /************************************************************************/
    7860             : /*                             ReadVarInt()                             */
    7861             : /************************************************************************/
    7862             : 
    7863             : template <class OutType>
    7864             : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW static bool
    7865        7011 : ReadVarInt(const GByte *&pabyIter, const GByte *pabyEnd, OutType &nOutVal)
    7866             : {
    7867             :     GUInt32 b;
    7868             : 
    7869        7011 :     if (pabyIter >= pabyEnd)
    7870          15 :         return false;
    7871        6996 :     b = *pabyIter;
    7872        6996 :     GUIntBig nVal = (b & 0x3F);
    7873        6996 :     bool bNegative = (b & 0x40) != 0;
    7874        6996 :     if ((b & 0x80) == 0)
    7875             :     {
    7876        1761 :         pabyIter++;
    7877        1761 :         if (bNegative)
    7878           4 :             nOutVal = -static_cast<OutType>(nVal);
    7879             :         else
    7880        1757 :             nOutVal = static_cast<OutType>(nVal);
    7881        1761 :         return true;
    7882             :     }
    7883             : 
    7884        5235 :     const GByte *pabyLocalIter = pabyIter + 1;
    7885        5235 :     int nShift = 6;
    7886        2179 :     while (true)
    7887             :     {
    7888        7414 :         if (pabyLocalIter >= pabyEnd)
    7889          23 :             return false;
    7890        7391 :         GUIntBig b64 = *pabyLocalIter;
    7891        7391 :         pabyLocalIter++;
    7892        7391 :         nVal |= (b64 & 0x7F) << nShift;
    7893        7391 :         if ((b64 & 0x80) == 0)
    7894             :         {
    7895        5212 :             pabyIter = pabyLocalIter;
    7896        5212 :             if (bNegative)
    7897         813 :                 nOutVal = -static_cast<OutType>(nVal);
    7898             :             else
    7899        4399 :                 nOutVal = static_cast<OutType>(nVal);
    7900        5212 :             return true;
    7901             :         }
    7902        2179 :         nShift += 7;
    7903             :         // To avoid undefined behavior later when doing << nShift
    7904        2179 :         if (nShift >= static_cast<int>(sizeof(GIntBig)) * 8)
    7905             :         {
    7906           0 :             return false;
    7907             :         }
    7908             :     }
    7909             : }
    7910             : 
    7911             : /************************************************************************/
    7912             : /*                          ReadUInt8()                                 */
    7913             : /************************************************************************/
    7914             : 
    7915        1207 : inline bool ReadUInt8(const GByte *&pabyIter, const GByte *pabyEnd, GByte &nVal)
    7916             : {
    7917        1207 :     if (pabyIter + sizeof(nVal) > pabyEnd)
    7918          10 :         return false;
    7919        1197 :     nVal = *pabyIter;
    7920        1197 :     pabyIter += sizeof(nVal);
    7921        1197 :     return true;
    7922             : }
    7923             : 
    7924             : /************************************************************************/
    7925             : /*                          ReadFloat32()                               */
    7926             : /************************************************************************/
    7927             : 
    7928         239 : inline bool ReadFloat32(const GByte *&pabyIter, const GByte *pabyEnd,
    7929             :                         float &fVal)
    7930             : {
    7931         239 :     if (pabyIter + sizeof(fVal) > pabyEnd)
    7932           8 :         return false;
    7933             :     // cppcheck-suppress bufferAccessOutOfBounds
    7934         231 :     memcpy(&fVal, pabyIter, sizeof(fVal));
    7935         231 :     CPL_LSBPTR32(&fVal);
    7936         231 :     pabyIter += sizeof(fVal);
    7937         231 :     return true;
    7938             : }
    7939             : 
    7940             : /************************************************************************/
    7941             : /*                          ReadFloat64()                               */
    7942             : /************************************************************************/
    7943             : 
    7944         541 : inline bool ReadFloat64(const GByte *&pabyIter, const GByte *pabyEnd,
    7945             :                         double &dfVal)
    7946             : {
    7947         541 :     if (pabyIter + sizeof(dfVal) > pabyEnd)
    7948          22 :         return false;
    7949         519 :     memcpy(&dfVal, pabyIter, sizeof(dfVal));
    7950         519 :     CPL_LSBPTR64(&dfVal);
    7951         519 :     pabyIter += sizeof(dfVal);
    7952         519 :     return true;
    7953             : }
    7954             : 
    7955             : }  // namespace
    7956             : 
    7957             : /************************************************************************/
    7958             : /*                    OGRFeature::DeserializeFromBinary()               */
    7959             : /************************************************************************/
    7960             : 
    7961             : /** Instantiate a feature from a binary encoding produces by SerializeToBinary()
    7962             :  *
    7963             :  * This sets the feature ID, attribute fields content and geometry fields
    7964             :  * content.
    7965             :  *
    7966             :  * DeserializeFromBinary() should be called on a feature whose feature definition
    7967             :  * is exactly the same as the one on which SerializeToBinary() was called.
    7968             :  * (but there is no security issue if not doing that, or if feeding a "random"
    7969             :  * buffer to that method).
    7970             :  *
    7971             :  * The format of that encoding may vary across GDAL versions.
    7972             :  *
    7973             :  * @since 3.9
    7974             :  */
    7975        2461 : bool OGRFeature::DeserializeFromBinary(const GByte *pabyBuffer, size_t nSize)
    7976             : {
    7977        2461 :     Reset();
    7978             : 
    7979        2461 :     const GByte *const pabyFlags = pabyBuffer;
    7980        2461 :     const GByte *const pabyEnd = pabyBuffer + nSize;
    7981        2461 :     const int nFieldCount = poDefn->GetFieldCount();
    7982        2461 :     const int nGeomFieldCount = poDefn->GetGeomFieldCount();
    7983        2461 :     const size_t nPresenceFlagsSize =
    7984        2461 :         ((2 * nFieldCount + nGeomFieldCount) + 7) / 8;
    7985        2461 :     if (nSize < nPresenceFlagsSize)
    7986          12 :         return false;
    7987        2449 :     pabyBuffer += nPresenceFlagsSize;
    7988             : 
    7989        2449 :     if (!ReadVarInt(pabyBuffer, pabyEnd, nFID))
    7990          11 :         return false;
    7991             : 
    7992       11105 :     const auto IsFlagBitSet = [pabyFlags](int iBit) -> bool
    7993       11105 :     { return (pabyFlags[iBit / 8] & (1 << (iBit % 8))) != 0; };
    7994             : 
    7995        6730 :     for (int i = 0; i < nFieldCount; ++i)
    7996             :     {
    7997        4412 :         OGRField &uField = pauFields[i];
    7998             :         {
    7999        4412 :             const int iBit = 2 * i;
    8000        4412 :             if (IsFlagBitSet(iBit))
    8001             :             {
    8002             :                 // OGR_RawField_SetUnset(&uField);
    8003          35 :                 continue;
    8004             :             }
    8005             :         }
    8006             :         {
    8007        4377 :             const int iBit = 2 * i + 1;
    8008        4377 :             if (IsFlagBitSet(iBit))
    8009             :             {
    8010           1 :                 OGR_RawField_SetNull(&uField);
    8011           1 :                 continue;
    8012             :             }
    8013             :         }
    8014        4376 :         const auto poFDefn = poDefn->GetFieldDefn(i);
    8015        4376 :         switch (poFDefn->GetType())
    8016             :         {
    8017        2433 :             case OFTInteger:
    8018             :             {
    8019        2433 :                 uField.Set.nMarker2 = 0;
    8020        2433 :                 uField.Set.nMarker3 = 0;
    8021        2433 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Integer))
    8022           2 :                     return false;
    8023        2431 :                 break;
    8024             :             }
    8025         227 :             case OFTInteger64:
    8026             :             {
    8027         227 :                 uField.Set.nMarker2 = 0;
    8028         227 :                 uField.Set.nMarker3 = 0;
    8029         227 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Integer64))
    8030           7 :                     return false;
    8031         220 :                 break;
    8032             :             }
    8033         220 :             case OFTReal:
    8034             :             {
    8035         220 :                 uField.Set.nMarker2 = 0;
    8036         220 :                 uField.Set.nMarker3 = 0;
    8037         220 :                 if (!ReadFloat64(pabyBuffer, pabyEnd, uField.Real))
    8038           8 :                     return false;
    8039         212 :                 break;
    8040             :             }
    8041         212 :             case OFTString:
    8042             :             {
    8043         212 :                 size_t nStrSize = 0;
    8044         423 :                 if (!ReadVarUInt(pabyBuffer, pabyEnd, nStrSize) ||
    8045         211 :                     nStrSize > std::numeric_limits<size_t>::max() - 1)
    8046             :                 {
    8047           9 :                     return false;
    8048             :                 }
    8049         211 :                 if (nStrSize > static_cast<size_t>(pabyEnd - pabyBuffer))
    8050           8 :                     return false;
    8051             :                 auto ptr =
    8052         203 :                     static_cast<char *>(VSI_MALLOC_VERBOSE(nStrSize + 1));
    8053         203 :                 if (!ptr)
    8054           0 :                     return false;
    8055         203 :                 uField.Set.nMarker2 = 0;
    8056         203 :                 uField.Set.nMarker3 = 0;
    8057         203 :                 uField.String = ptr;
    8058         203 :                 memcpy(uField.String, pabyBuffer, nStrSize);
    8059         203 :                 uField.String[nStrSize] = 0;
    8060         203 :                 pabyBuffer += nStrSize;
    8061         203 :                 break;
    8062             :             }
    8063         196 :             case OFTIntegerList:
    8064             :             {
    8065         196 :                 int nCount = 0;
    8066         388 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
    8067         192 :                     nCount > pabyEnd - pabyBuffer)
    8068             :                 {
    8069          11 :                     return false;
    8070             :                 }
    8071             :                 auto ptr = static_cast<int *>(
    8072         190 :                     VSI_MALLOC2_VERBOSE(nCount, sizeof(int)));
    8073         190 :                 if (!ptr)
    8074           3 :                     return false;
    8075         187 :                 uField.Set.nMarker2 = 0;
    8076         187 :                 uField.Set.nMarker3 = 0;
    8077         187 :                 uField.IntegerList.paList = ptr;
    8078         187 :                 uField.IntegerList.nCount = nCount;
    8079         559 :                 for (int j = 0; j < nCount; ++j)
    8080             :                 {
    8081         374 :                     if (!ReadVarInt(pabyBuffer, pabyEnd,
    8082         374 :                                     uField.IntegerList.paList[j]))
    8083           2 :                         return false;
    8084             :                 }
    8085         185 :                 break;
    8086             :             }
    8087         185 :             case OFTInteger64List:
    8088             :             {
    8089         185 :                 int nCount = 0;
    8090         368 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
    8091         183 :                     nCount > pabyEnd - pabyBuffer)
    8092             :                 {
    8093          11 :                     return false;
    8094             :                 }
    8095             :                 auto ptr = static_cast<GIntBig *>(
    8096         180 :                     VSI_MALLOC2_VERBOSE(nCount, sizeof(GIntBig)));
    8097         180 :                 if (!ptr)
    8098           0 :                     return false;
    8099         180 :                 uField.Set.nMarker2 = 0;
    8100         180 :                 uField.Set.nMarker3 = 0;
    8101         180 :                 uField.Integer64List.paList = ptr;
    8102         180 :                 uField.Integer64List.nCount = nCount;
    8103         545 :                 for (int j = 0; j < nCount; ++j)
    8104             :                 {
    8105         371 :                     if (!ReadVarInt(pabyBuffer, pabyEnd,
    8106         371 :                                     uField.Integer64List.paList[j]))
    8107           6 :                         return false;
    8108             :                 }
    8109         174 :                 break;
    8110             :             }
    8111         174 :             case OFTRealList:
    8112             :             {
    8113         174 :                 int nCount = 0;
    8114         343 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
    8115         169 :                     nCount > pabyEnd - pabyBuffer)
    8116             :                 {
    8117          26 :                     return false;
    8118             :                 }
    8119             :                 auto ptr = static_cast<double *>(
    8120         165 :                     VSI_MALLOC2_VERBOSE(nCount, sizeof(double)));
    8121         165 :                 if (!ptr)
    8122           3 :                     return false;
    8123         162 :                 uField.Set.nMarker2 = 0;
    8124         162 :                 uField.Set.nMarker3 = 0;
    8125         162 :                 uField.RealList.paList = ptr;
    8126         162 :                 uField.RealList.nCount = nCount;
    8127         469 :                 for (int j = 0; j < nCount; ++j)
    8128             :                 {
    8129         321 :                     if (!ReadFloat64(pabyBuffer, pabyEnd,
    8130         321 :                                      uField.RealList.paList[j]))
    8131          14 :                         return false;
    8132             :                 }
    8133         148 :                 break;
    8134             :             }
    8135         148 :             case OFTStringList:
    8136             :             {
    8137         148 :                 int nCount = 0;
    8138         295 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
    8139         441 :                     nCount > std::numeric_limits<int>::max() - 1 ||
    8140         146 :                     nCount > pabyEnd - pabyBuffer)
    8141             :                 {
    8142          17 :                     return false;
    8143             :                 }
    8144             :                 auto ptr = static_cast<char **>(
    8145         143 :                     VSI_CALLOC_VERBOSE(nCount + 1, sizeof(char *)));
    8146         143 :                 if (!ptr)
    8147           0 :                     return false;
    8148         143 :                 uField.Set.nMarker2 = 0;
    8149         143 :                 uField.Set.nMarker3 = 0;
    8150         143 :                 uField.StringList.paList = ptr;
    8151         143 :                 uField.StringList.nCount = nCount;
    8152         413 :                 for (int j = 0; j < nCount; ++j)
    8153             :                 {
    8154         282 :                     size_t nStrSize = 0;
    8155         563 :                     if (!ReadVarUInt(pabyBuffer, pabyEnd, nStrSize) ||
    8156         281 :                         nStrSize > std::numeric_limits<size_t>::max() - 1)
    8157             :                     {
    8158          12 :                         return false;
    8159             :                     }
    8160         281 :                     if (nStrSize > static_cast<size_t>(pabyEnd - pabyBuffer))
    8161          11 :                         return false;
    8162         540 :                     uField.StringList.paList[j] =
    8163         270 :                         static_cast<char *>(VSI_MALLOC_VERBOSE(nStrSize + 1));
    8164         270 :                     if (!uField.StringList.paList[j])
    8165           0 :                         return false;
    8166         270 :                     memcpy(uField.StringList.paList[j], pabyBuffer, nStrSize);
    8167         270 :                     uField.StringList.paList[j][nStrSize] = 0;
    8168         270 :                     pabyBuffer += nStrSize;
    8169             :                 }
    8170         131 :                 break;
    8171             :             }
    8172         203 :             case OFTBinary:
    8173             :             {
    8174         203 :                 int nBinSize = 0;
    8175         203 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, nBinSize) || nBinSize < 0)
    8176             :                 {
    8177           7 :                     return false;
    8178             :                 }
    8179         199 :                 if (nBinSize > pabyEnd - pabyBuffer)
    8180           3 :                     return false;
    8181         196 :                 auto ptr = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nBinSize));
    8182         196 :                 if (!ptr)
    8183           0 :                     return false;
    8184         196 :                 uField.Set.nMarker2 = 0;
    8185         196 :                 uField.Set.nMarker3 = 0;
    8186         196 :                 uField.Binary.paData = ptr;
    8187         196 :                 uField.Binary.nCount = nBinSize;
    8188         196 :                 memcpy(uField.Binary.paData, pabyBuffer, nBinSize);
    8189         196 :                 pabyBuffer += nBinSize;
    8190         196 :                 break;
    8191             :             }
    8192           0 :             case OFTWideString:
    8193             :             case OFTWideStringList:
    8194           0 :                 break;
    8195         131 :             case OFTDate:
    8196             :             {
    8197         131 :                 memset(&uField, 0, sizeof(uField));
    8198         131 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Date.Year) ||
    8199         259 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Month) ||
    8200         128 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Day))
    8201             :                 {
    8202           4 :                     return false;
    8203             :                 }
    8204         127 :                 break;
    8205             :             }
    8206         127 :             case OFTTime:
    8207             :             {
    8208         127 :                 memset(&uField, 0, sizeof(uField));
    8209         127 :                 if (!ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Hour) ||
    8210         126 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Minute) ||
    8211         374 :                     !ReadFloat32(pabyBuffer, pabyEnd, uField.Date.Second) ||
    8212         121 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.TZFlag))
    8213             :                 {
    8214           7 :                     return false;
    8215             :                 }
    8216         120 :                 break;
    8217             :             }
    8218         120 :             case OFTDateTime:
    8219             :             {
    8220         120 :                 memset(&uField, 0, sizeof(uField));
    8221         120 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Date.Year) ||
    8222         118 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Month) ||
    8223         117 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Day) ||
    8224         116 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Hour) ||
    8225         115 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Minute) ||
    8226         348 :                     !ReadFloat32(pabyBuffer, pabyEnd, uField.Date.Second) ||
    8227         110 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.TZFlag))
    8228             :                 {
    8229          11 :                     return false;
    8230             :                 }
    8231         109 :                 break;
    8232             :             }
    8233             :         }
    8234             :     }
    8235        4602 :     for (int i = 0; i < nGeomFieldCount; ++i)
    8236             :     {
    8237        2316 :         const int iBit = 2 * nFieldCount + i;
    8238        2316 :         if (IsFlagBitSet(iBit))
    8239             :         {
    8240        1005 :             continue;
    8241             :         }
    8242        1311 :         size_t nWkbSize = 0;
    8243        1311 :         if (!ReadVarUInt(pabyBuffer, pabyEnd, nWkbSize))
    8244             :         {
    8245          32 :             return false;
    8246             :         }
    8247        1310 :         if (nWkbSize > static_cast<size_t>(pabyEnd - pabyBuffer))
    8248             :         {
    8249          23 :             return false;
    8250             :         }
    8251        1287 :         OGRGeometry *poGeom = nullptr;
    8252        1287 :         if (OGRGeometryFactory::createFromWkb(
    8253        1287 :                 pabyBuffer, poDefn->GetGeomFieldDefn(i)->GetSpatialRef(),
    8254        2566 :                 &poGeom, nWkbSize, wkbVariantIso) != OGRERR_NONE ||
    8255        1279 :             !poGeom)
    8256             :         {
    8257           8 :             delete poGeom;
    8258           8 :             return false;
    8259             :         }
    8260        1279 :         pabyBuffer += nWkbSize;
    8261        1279 :         papoGeometries[i] = poGeom;
    8262             :     }
    8263        2286 :     return true;
    8264             : }
    8265             : 
    8266             : /************************************************************************/
    8267             : /*                    OGRFeature::ConstFieldIterator                    */
    8268             : /************************************************************************/
    8269             : 
    8270             : struct OGRFeature::FieldValue::Private
    8271             : {
    8272             :     CPL_DISALLOW_COPY_ASSIGN(Private)
    8273             : 
    8274             :     OGRFeature *m_poSelf = nullptr;
    8275             :     int m_nPos = 0;
    8276             :     mutable std::vector<int> m_anList{};
    8277             :     mutable std::vector<GIntBig> m_anList64{};
    8278             :     mutable std::vector<double> m_adfList{};
    8279             :     mutable std::vector<std::string> m_aosList{};
    8280             : 
    8281           4 :     Private(const OGRFeature *poSelf, int iFieldIndex)
    8282           4 :         : m_poSelf(const_cast<OGRFeature *>(poSelf)), m_nPos(iFieldIndex)
    8283             :     {
    8284           4 :     }
    8285             : 
    8286          47 :     Private(OGRFeature *poSelf, int iFieldIndex)
    8287          47 :         : m_poSelf(poSelf), m_nPos(iFieldIndex)
    8288             :     {
    8289          47 :     }
    8290             : };
    8291             : 
    8292             : struct OGRFeature::ConstFieldIterator::Private
    8293             : {
    8294             :     CPL_DISALLOW_COPY_ASSIGN(Private)
    8295             : 
    8296             :     OGRFeature::FieldValue m_oValue;
    8297             :     int m_nPos = 0;
    8298             : 
    8299           4 :     Private(const OGRFeature *poSelf, int iFieldIndex)
    8300           4 :         : m_oValue(poSelf, iFieldIndex)
    8301             :     {
    8302           4 :     }
    8303             : };
    8304             : 
    8305             : //! @cond Doxygen_Suppress
    8306           4 : OGRFeature::ConstFieldIterator::ConstFieldIterator(const OGRFeature *poSelf,
    8307           4 :                                                    int nPos)
    8308           4 :     : m_poPrivate(new Private(poSelf, nPos))
    8309             : {
    8310           4 :     m_poPrivate->m_nPos = nPos;
    8311           4 : }
    8312             : 
    8313             : OGRFeature::ConstFieldIterator::~ConstFieldIterator() = default;
    8314             : 
    8315          22 : const OGRFeature::FieldValue &OGRFeature::ConstFieldIterator::operator*() const
    8316             : {
    8317          22 :     return m_poPrivate->m_oValue;
    8318             : }
    8319             : 
    8320          22 : OGRFeature::ConstFieldIterator &OGRFeature::ConstFieldIterator::operator++()
    8321             : {
    8322          22 :     ++m_poPrivate->m_nPos;
    8323          22 :     m_poPrivate->m_oValue.m_poPrivate->m_nPos = m_poPrivate->m_nPos;
    8324          22 :     return *this;
    8325             : }
    8326             : 
    8327          24 : bool OGRFeature::ConstFieldIterator::operator!=(
    8328             :     const ConstFieldIterator &it) const
    8329             : {
    8330          24 :     return m_poPrivate->m_nPos != it.m_poPrivate->m_nPos;
    8331             : }
    8332             : 
    8333             : //! @endcond
    8334             : 
    8335           2 : OGRFeature::ConstFieldIterator OGRFeature::begin() const
    8336             : {
    8337           2 :     return {this, 0};
    8338             : }
    8339             : 
    8340           2 : OGRFeature::ConstFieldIterator OGRFeature::end() const
    8341             : {
    8342           2 :     return {this, GetFieldCount()};
    8343             : }
    8344             : 
    8345             : /************************************************************************/
    8346             : /*                      OGRFeature::FieldValue                          */
    8347             : /************************************************************************/
    8348             : 
    8349           4 : OGRFeature::FieldValue::FieldValue(const OGRFeature *poFeature, int iFieldIndex)
    8350           4 :     : m_poPrivate(new Private(poFeature, iFieldIndex))
    8351             : {
    8352           4 : }
    8353             : 
    8354          47 : OGRFeature::FieldValue::FieldValue(OGRFeature *poFeature, int iFieldIndex)
    8355          47 :     : m_poPrivate(new Private(poFeature, iFieldIndex))
    8356             : {
    8357          47 : }
    8358             : 
    8359          14 : OGRFeature::FieldValue &OGRFeature::FieldValue::Assign(const FieldValue &oOther)
    8360             : {
    8361          27 :     if (&oOther != this &&
    8362          13 :         !(m_poPrivate->m_poSelf == oOther.m_poPrivate->m_poSelf &&
    8363           2 :           m_poPrivate->m_nPos == oOther.m_poPrivate->m_nPos))
    8364             :     {
    8365          12 :         OGRFieldType eOtherType(oOther.GetType());
    8366          12 :         if (oOther.IsNull())
    8367           1 :             SetNull();
    8368          11 :         else if (oOther.IsUnset())
    8369           1 :             Unset();
    8370          10 :         else if (eOtherType == OFTInteger)
    8371           2 :             m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8372             :                                             oOther.GetInteger());
    8373           8 :         else if (eOtherType == OFTInteger64)
    8374           1 :             m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8375             :                                             oOther.GetInteger64());
    8376           7 :         else if (eOtherType == OFTReal)
    8377           1 :             m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8378             :                                             oOther.GetDouble());
    8379           6 :         else if (eOtherType == OFTString)
    8380           1 :             m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8381             :                                             oOther.GetString());
    8382           5 :         else if (eOtherType == OFTDate || eOtherType == OFTDateTime ||
    8383             :                  eOtherType == OFTTime)
    8384             :         {
    8385           1 :             int nYear = 0;
    8386           1 :             int nMonth = 0;
    8387           1 :             int nDay = 0;
    8388           1 :             int nHour = 0;
    8389           1 :             int nMinute = 0;
    8390           1 :             float fSecond = 0.0f;
    8391           1 :             int nTZFlag = 0;
    8392           1 :             oOther.GetDateTime(&nYear, &nMonth, &nDay, &nHour, &nMinute,
    8393             :                                &fSecond, &nTZFlag);
    8394           1 :             m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nYear, nMonth,
    8395             :                                             nDay, nHour, nMinute, fSecond,
    8396           1 :                                             nTZFlag);
    8397             :         }
    8398           4 :         else if (eOtherType == OFTStringList)
    8399             :         {
    8400           2 :             m_poPrivate->m_poSelf->SetField(
    8401           1 :                 m_poPrivate->m_nPos,
    8402           2 :                 oOther.m_poPrivate->m_poSelf->GetFieldAsStringList(
    8403           1 :                     oOther.m_poPrivate->m_nPos));
    8404             :         }
    8405           3 :         else if (eOtherType == OFTIntegerList)
    8406             :         {
    8407           1 :             operator=(oOther.GetAsIntegerList());
    8408             :         }
    8409           2 :         else if (eOtherType == OFTInteger64List)
    8410             :         {
    8411           1 :             operator=(oOther.GetAsInteger64List());
    8412             :         }
    8413           1 :         else if (eOtherType == OFTRealList)
    8414             :         {
    8415           1 :             operator=(oOther.GetAsDoubleList());
    8416             :         }
    8417             :     }
    8418          14 :     return *this;
    8419             : }
    8420             : 
    8421             : OGRFeature::FieldValue &
    8422          12 : OGRFeature::FieldValue::operator=(const FieldValue &oOther)
    8423             : {
    8424          12 :     return Assign(oOther);
    8425             : }
    8426             : 
    8427             : //! @cond Doxygen_Suppress
    8428           2 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(FieldValue &&oOther)
    8429             : {
    8430           2 :     return Assign(oOther);
    8431             : }
    8432             : 
    8433             : //! @endcond
    8434             : 
    8435           1 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(int nVal)
    8436             : {
    8437           1 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nVal);
    8438           1 :     return *this;
    8439             : }
    8440             : 
    8441           1 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(GIntBig nVal)
    8442             : {
    8443           1 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nVal);
    8444           1 :     return *this;
    8445             : }
    8446             : 
    8447           1 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(double dfVal)
    8448             : {
    8449           1 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, dfVal);
    8450           1 :     return *this;
    8451             : }
    8452             : 
    8453           2 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(const char *pszVal)
    8454             : {
    8455           2 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, pszVal);
    8456           2 :     return *this;
    8457             : }
    8458             : 
    8459             : OGRFeature::FieldValue &
    8460           1 : OGRFeature::FieldValue::operator=(const std::string &osVal)
    8461             : {
    8462           1 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, osVal.c_str());
    8463           1 :     return *this;
    8464             : }
    8465             : 
    8466             : OGRFeature::FieldValue &
    8467           3 : OGRFeature::FieldValue::operator=(const std::vector<int> &oArray)
    8468             : {
    8469           9 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8470           3 :                                     static_cast<int>(oArray.size()),
    8471           5 :                                     oArray.empty() ? nullptr : oArray.data());
    8472           3 :     return *this;
    8473             : }
    8474             : 
    8475             : OGRFeature::FieldValue &
    8476           3 : OGRFeature::FieldValue::operator=(const std::vector<GIntBig> &oArray)
    8477             : {
    8478           9 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8479           3 :                                     static_cast<int>(oArray.size()),
    8480           5 :                                     oArray.empty() ? nullptr : oArray.data());
    8481           3 :     return *this;
    8482             : }
    8483             : 
    8484             : OGRFeature::FieldValue &
    8485           3 : OGRFeature::FieldValue::operator=(const std::vector<double> &oArray)
    8486             : {
    8487           9 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8488           3 :                                     static_cast<int>(oArray.size()),
    8489           5 :                                     oArray.empty() ? nullptr : oArray.data());
    8490           3 :     return *this;
    8491             : }
    8492             : 
    8493             : OGRFeature::FieldValue &
    8494           2 : OGRFeature::FieldValue::operator=(const std::vector<std::string> &oArray)
    8495             : {
    8496           2 :     CPLStringList aosList;
    8497           4 :     for (auto &&oStr : oArray)
    8498           2 :         aosList.AddString(oStr.c_str());
    8499           2 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, aosList.List());
    8500           4 :     return *this;
    8501             : }
    8502             : 
    8503             : OGRFeature::FieldValue &
    8504           2 : OGRFeature::FieldValue::operator=(CSLConstList papszValues)
    8505             : {
    8506           2 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, papszValues);
    8507           2 :     return *this;
    8508             : }
    8509             : 
    8510           1 : void OGRFeature::FieldValue::SetDateTime(int nYear, int nMonth, int nDay,
    8511             :                                          int nHour, int nMinute, float fSecond,
    8512             :                                          int nTZFlag)
    8513             : {
    8514           1 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nYear, nMonth, nDay,
    8515             :                                     nHour, nMinute, fSecond, nTZFlag);
    8516           1 : }
    8517             : 
    8518           2 : void OGRFeature::FieldValue::SetNull()
    8519             : {
    8520           2 :     m_poPrivate->m_poSelf->SetFieldNull(m_poPrivate->m_nPos);
    8521           2 : }
    8522             : 
    8523           3 : void OGRFeature::FieldValue::clear()
    8524             : {
    8525           3 :     m_poPrivate->m_poSelf->UnsetField(m_poPrivate->m_nPos);
    8526           3 : }
    8527             : 
    8528             : //! @cond Doxygen_Suppress
    8529             : OGRFeature::FieldValue::~FieldValue() = default;
    8530             : 
    8531             : //! @endcond
    8532             : 
    8533         188 : int OGRFeature::FieldValue::GetIndex() const
    8534             : {
    8535         188 :     return m_poPrivate->m_nPos;
    8536             : }
    8537             : 
    8538          89 : const OGRFieldDefn *OGRFeature::FieldValue::GetDefn() const
    8539             : {
    8540          89 :     return m_poPrivate->m_poSelf->GetFieldDefnRef(GetIndex());
    8541             : }
    8542             : 
    8543          48 : const OGRField *OGRFeature::FieldValue::GetRawValue() const
    8544             : {
    8545          48 :     return &(m_poPrivate->m_poSelf->pauFields[GetIndex()]);
    8546             : }
    8547             : 
    8548          15 : bool OGRFeature::FieldValue::IsUnset() const
    8549             : {
    8550          15 :     return CPL_TO_BOOL(OGR_RawField_IsUnset(GetRawValue()));
    8551             : }
    8552             : 
    8553          15 : bool OGRFeature::FieldValue::IsNull() const
    8554             : {
    8555          15 :     return CPL_TO_BOOL(OGR_RawField_IsNull(GetRawValue()));
    8556             : }
    8557             : 
    8558           5 : int OGRFeature::FieldValue::GetAsInteger() const
    8559             : {
    8560           5 :     return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8561           5 :         ->GetFieldAsInteger(GetIndex());
    8562             : }
    8563             : 
    8564           4 : GIntBig OGRFeature::FieldValue::GetAsInteger64() const
    8565             : {
    8566           4 :     return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8567           4 :         ->GetFieldAsInteger64(GetIndex());
    8568             : }
    8569             : 
    8570           4 : double OGRFeature::FieldValue::GetAsDouble() const
    8571             : {
    8572           4 :     return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8573           4 :         ->GetFieldAsDouble(GetIndex());
    8574             : }
    8575             : 
    8576           5 : const char *OGRFeature::FieldValue::GetAsString() const
    8577             : {
    8578           5 :     return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8579           5 :         ->GetFieldAsString(GetIndex());
    8580             : }
    8581             : 
    8582           2 : bool OGRFeature::FieldValue::GetDateTime(int *pnYear, int *pnMonth, int *pnDay,
    8583             :                                          int *pnHour, int *pnMinute,
    8584             :                                          float *pfSecond, int *pnTZFlag) const
    8585             : {
    8586           2 :     return CPL_TO_BOOL(const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8587             :                            ->GetFieldAsDateTime(GetIndex(), pnYear, pnMonth,
    8588             :                                                 pnDay, pnHour, pnMinute,
    8589           2 :                                                 pfSecond, pnTZFlag));
    8590             : }
    8591             : 
    8592           2 : const std::vector<int> &OGRFeature::FieldValue::GetAsIntegerList() const
    8593             : {
    8594           2 :     int nCount = 0;
    8595           2 :     auto &&panList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8596           2 :                          ->GetFieldAsIntegerList(GetIndex(), &nCount);
    8597           2 :     m_poPrivate->m_anList.assign(panList, panList + nCount);
    8598           2 :     return m_poPrivate->m_anList;
    8599             : }
    8600             : 
    8601           2 : const std::vector<GIntBig> &OGRFeature::FieldValue::GetAsInteger64List() const
    8602             : {
    8603           2 :     int nCount = 0;
    8604           2 :     auto &&panList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8605           2 :                          ->GetFieldAsInteger64List(GetIndex(), &nCount);
    8606           2 :     m_poPrivate->m_anList64.assign(panList, panList + nCount);
    8607           2 :     return m_poPrivate->m_anList64;
    8608             : }
    8609             : 
    8610           2 : const std::vector<double> &OGRFeature::FieldValue::GetAsDoubleList() const
    8611             : {
    8612           2 :     int nCount = 0;
    8613           2 :     auto &&panList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8614           2 :                          ->GetFieldAsDoubleList(GetIndex(), &nCount);
    8615           2 :     m_poPrivate->m_adfList.assign(panList, panList + nCount);
    8616           2 :     return m_poPrivate->m_adfList;
    8617             : }
    8618             : 
    8619           1 : const std::vector<std::string> &OGRFeature::FieldValue::GetAsStringList() const
    8620             : {
    8621           1 :     auto &&papszList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8622           1 :                            ->GetFieldAsStringList(GetIndex());
    8623           1 :     m_poPrivate->m_aosList.clear();
    8624           1 :     if (papszList)
    8625             :     {
    8626           3 :         for (char **papszIter = papszList; *papszIter; ++papszIter)
    8627             :         {
    8628           2 :             m_poPrivate->m_aosList.emplace_back(*papszIter);
    8629             :         }
    8630             :     }
    8631           1 :     return m_poPrivate->m_aosList;
    8632             : }
    8633             : 
    8634           2 : OGRFeature::FieldValue::operator CSLConstList() const
    8635             : {
    8636             :     return const_cast<CSLConstList>(
    8637           2 :         const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8638           2 :             ->GetFieldAsStringList(GetIndex()));
    8639             : }
    8640             : 
    8641          14 : OGRRangeFieldDomain *OGRRangeFieldDomain::Clone() const
    8642             : {
    8643             :     auto poDomain = new OGRRangeFieldDomain(
    8644          14 :         m_osName, m_osDescription, m_eFieldType, m_eFieldSubType, m_sMin,
    8645          14 :         m_bMinIsInclusive, m_sMax, m_bMaxIsInclusive);
    8646          14 :     poDomain->SetMergePolicy(m_eMergePolicy);
    8647          14 :     poDomain->SetSplitPolicy(m_eSplitPolicy);
    8648          14 :     return poDomain;
    8649             : }
    8650             : 
    8651          15 : OGRGlobFieldDomain *OGRGlobFieldDomain::Clone() const
    8652             : {
    8653             :     auto poDomain = new OGRGlobFieldDomain(
    8654          15 :         m_osName, m_osDescription, m_eFieldType, m_eFieldSubType, m_osGlob);
    8655          15 :     poDomain->SetMergePolicy(m_eMergePolicy);
    8656          15 :     poDomain->SetSplitPolicy(m_eSplitPolicy);
    8657          15 :     return poDomain;
    8658             : }
    8659             : #if defined(__GNUC__)
    8660             : #pragma GCC diagnostic pop
    8661             : #endif

Generated by: LCOV version 1.14