LCOV - code coverage report
Current view: top level - ogr - ogrfeature.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 2533 2797 90.6 %
Date: 2026-02-23 15:56:29 Functions: 195 211 92.4 %

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

Generated by: LCOV version 1.14