LCOV - code coverage report
Current view: top level - ogr - ogrfeature.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 2495 2738 91.1 %
Date: 2024-05-04 12:52:34 Functions: 191 206 92.7 %

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

Generated by: LCOV version 1.14