LCOV - code coverage report
Current view: top level - ogr - ogrfeature.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 2510 2769 90.6 %
Date: 2024-11-21 22:18:42 Functions: 191 208 91.8 %

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

Generated by: LCOV version 1.14