LCOV - code coverage report
Current view: top level - ogr - ogrfeature.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 2533 2783 91.0 %
Date: 2026-02-01 11:59:10 Functions: 195 210 92.9 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  The OGRFeature class implementation.
       5             :  * Author:   Frank Warmerdam, warmerda@home.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
       9             :  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "ogr_api.h"
      16             : #include "ogr_feature.h"
      17             : 
      18             : #include <cerrno>
      19             : #include <cinttypes>
      20             : #include <climits>
      21             : #include <cstdio>
      22             : #include <cstdlib>
      23             : #include <cstring>
      24             : #include <cmath>
      25             : #include <ctime>
      26             : 
      27             : #include <algorithm>
      28             : #include <limits>
      29             : #include <map>
      30             : #include <new>
      31             : #include <vector>
      32             : 
      33             : #include "cpl_conv.h"
      34             : #include "cpl_error.h"
      35             : #include "cpl_string.h"
      36             : #include "cpl_time.h"
      37             : #include "cpl_vsi.h"
      38             : #include "ogr_core.h"
      39             : #include "ogr_featurestyle.h"
      40             : #include "ogr_geometry.h"
      41             : #include "ogr_p.h"
      42             : #include "ogrlibjsonutils.h"
      43             : 
      44             : #include "cpl_json_header.h"
      45             : 
      46             : // Too many false positives from gcc 13.2.1 in that file...
      47             : #if defined(__GNUC__)
      48             : #pragma GCC diagnostic push
      49             : #pragma GCC diagnostic ignored "-Wnull-dereference"
      50             : #endif
      51             : 
      52             : /************************************************************************/
      53             : /*                             OGRFeature()                             */
      54             : /************************************************************************/
      55             : 
      56             : /**
      57             :  * \brief Constructor
      58             :  *
      59             :  * Note that the OGRFeature will increment the reference count of its
      60             :  * defining OGRFeatureDefn.  Destruction of the OGRFeatureDefn before
      61             :  * destruction of all OGRFeatures that depend on it is likely to result in
      62             :  * a crash.
      63             :  *
      64             :  * This method is the same as the C function OGR_F_Create().
      65             :  *
      66             :  * @param poDefnIn feature class (layer) definition to which the feature will
      67             :  * adhere.
      68             :  */
      69             : 
      70     2053370 : 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     2053370 :       m_poStyleTable(nullptr), m_pszTmpFieldValue(nullptr)
      75             : {
      76     2053370 :     const_cast<OGRFeatureDefn *>(poDefnIn)->Reference();
      77             : 
      78     2053370 :     const int nFieldCount = poDefn->GetFieldCount();
      79     2053370 :     pauFields = static_cast<OGRField *>(
      80     2053370 :         VSI_MALLOC_VERBOSE(nFieldCount * sizeof(OGRField)));
      81             : 
      82     2053370 :     papoGeometries = static_cast<OGRGeometry **>(
      83     2053370 :         VSI_CALLOC_VERBOSE(poDefn->GetGeomFieldCount(), sizeof(OGRGeometry *)));
      84             : 
      85             :     // Initialize array to the unset special value.
      86     2053370 :     if (pauFields != nullptr)
      87             :     {
      88    12963100 :         for (int i = 0; i < nFieldCount; i++)
      89             :         {
      90    10909700 :             pauFields[i].Set.nMarker1 = OGRUnsetMarker;
      91    10909700 :             pauFields[i].Set.nMarker2 = OGRUnsetMarker;
      92    10909700 :             pauFields[i].Set.nMarker3 = OGRUnsetMarker;
      93             :         }
      94             :     }
      95     2053370 : }
      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      127901 : OGRFeatureH OGR_F_Create(OGRFeatureDefnH hDefn)
     118             : 
     119             : {
     120      127901 :     VALIDATE_POINTER1(hDefn, "OGR_F_Create", nullptr);
     121      127901 :     return OGRFeature::ToHandle(
     122      255802 :         OGRFeature::CreateFeature(OGRFeatureDefn::FromHandle(hDefn)));
     123             : }
     124             : 
     125             : /************************************************************************/
     126             : /*                            ~OGRFeature()                             */
     127             : /************************************************************************/
     128             : 
     129     5599150 : OGRFeature::~OGRFeature()
     130             : 
     131             : {
     132     2053340 :     if (pauFields != nullptr)
     133             :     {
     134             :         // We can call GetFieldCountUnsafe() as the constructor has called
     135             :         // the regular GetFieldCount()
     136     2053340 :         const int nFieldcount = poDefn->GetFieldCountUnsafe();
     137    12963500 :         for (int i = 0; i < nFieldcount; i++)
     138             :         {
     139    10910200 :             const OGRFieldDefn *poFDefn = poDefn->GetFieldDefnUnsafe(i);
     140             : 
     141    10910200 :             if (!IsFieldSetAndNotNullUnsafe(i))
     142     3412200 :                 continue;
     143             : 
     144     7497980 :             switch (poFDefn->GetType())
     145             :             {
     146     4060210 :                 case OFTString:
     147     4060210 :                     if (pauFields[i].String != nullptr)
     148     4060110 :                         VSIFree(pauFields[i].String);
     149     4060210 :                     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       23765 :                 case OFTStringList:
     157       23765 :                     CSLDestroy(pauFields[i].StringList.paList);
     158       23765 :                     break;
     159             : 
     160       81322 :                 case OFTIntegerList:
     161             :                 case OFTInteger64List:
     162             :                 case OFTRealList:
     163       81322 :                     CPLFree(pauFields[i].IntegerList.paList);
     164       81322 :                     break;
     165             : 
     166     3273980 :                 default:
     167             :                     // TODO(schwehr): Add support for wide strings.
     168     3273980 :                     break;
     169             :             }
     170             :         }
     171             :     }
     172             : 
     173     2053340 :     if (papoGeometries != nullptr)
     174             :     {
     175     2053340 :         const int nGeomFieldCount = poDefn->GetGeomFieldCount();
     176             : 
     177     3361790 :         for (int i = 0; i < nGeomFieldCount; i++)
     178             :         {
     179     1308450 :             delete papoGeometries[i];
     180             :         }
     181             :     }
     182             : 
     183     2053340 :     if (poDefn)
     184     2053340 :         const_cast<OGRFeatureDefn *>(poDefn)->Release();
     185             : 
     186     2053340 :     CPLFree(pauFields);
     187     2053340 :     CPLFree(papoGeometries);
     188     2053340 :     CPLFree(m_pszStyleString);
     189     2053340 :     CPLFree(m_pszTmpFieldValue);
     190     2053340 :     CPLFree(m_pszNativeData);
     191     2053340 :     CPLFree(m_pszNativeMediaType);
     192     3545810 : }
     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      214968 : void OGR_F_Destroy(OGRFeatureH hFeat)
     212             : 
     213             : {
     214      214968 :     delete OGRFeature::FromHandle(hFeat);
     215      214968 : }
     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      483090 : OGRFeature *OGRFeature::CreateFeature(const OGRFeatureDefn *poDefn)
     238             : 
     239             : {
     240      483090 :     OGRFeature *poFeature = new (std::nothrow) OGRFeature(poDefn);
     241      483090 :     if (poFeature == nullptr)
     242           0 :         return nullptr;
     243             : 
     244           0 :     if ((poFeature->pauFields == nullptr &&
     245      966180 :          poDefn->GetFieldCountUnsafe() != 0) ||
     246      483090 :         (poFeature->papoGeometries == nullptr &&
     247           0 :          poDefn->GetGeomFieldCount() != 0))
     248             :     {
     249           0 :         delete poFeature;
     250           0 :         return nullptr;
     251             :     }
     252             : 
     253      483090 :     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       66277 : void OGRFeature::DestroyFeature(OGRFeature *poFeature)
     275             : 
     276             : {
     277       66277 :     delete poFeature;
     278       66277 : }
     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       26653 : void OGRFeature::SetFDefnUnsafe(OGRFeatureDefn *poNewFDefn)
     372             : {
     373       26653 :     poNewFDefn->Reference();
     374       26653 :     const_cast<OGRFeatureDefn *>(poDefn)->Release();
     375       26653 :     poDefn = poNewFDefn;
     376       26653 : }
     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       47990 : OGRFeatureDefnH OGR_F_GetDefnRef(OGRFeatureH hFeat)
     420             : 
     421             : {
     422       47990 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetDefnRef", nullptr);
     423             : 
     424       47990 :     return OGRFeatureDefn::ToHandle(const_cast<OGRFeatureDefn *>(
     425       95980 :         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      789700 : OGRErr OGRFeature::SetGeometryDirectly(OGRGeometry *poGeomIn)
     456             : 
     457             : {
     458      789700 :     if (poGeomIn == GetGeometryRef())
     459             :     {
     460         872 :         return OGRERR_NONE;
     461             :     }
     462             : 
     463      788828 :     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       39560 : OGRErr OGR_F_SetGeometryDirectly(OGRFeatureH hFeat, OGRGeometryH hGeom)
     494             : 
     495             : {
     496       39560 :     VALIDATE_POINTER1(hFeat, "OGR_F_SetGeometryDirectly", OGRERR_FAILURE);
     497             : 
     498       39560 :     return OGRFeature::FromHandle(hFeat)->SetGeometryDirectly(
     499       39560 :         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      236879 : OGRErr OGRFeature::SetGeometry(const OGRGeometry *poGeomIn)
     530             : 
     531             : {
     532      236879 :     if (GetGeomFieldCount() < 1)
     533           2 :         return OGRERR_FAILURE;
     534             : 
     535      236877 :     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      236508 : OGRErr OGR_F_SetGeometry(OGRFeatureH hFeat, OGRGeometryH hGeom)
     565             : 
     566             : {
     567      236508 :     VALIDATE_POINTER1(hFeat, "OGR_F_SetGeometry", OGRERR_FAILURE);
     568             : 
     569      473016 :     return OGRFeature::FromHandle(hFeat)->SetGeometry(
     570      473016 :         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      334814 : OGRErr OGRFeature::SetGeometry(std::unique_ptr<OGRGeometry> poGeomIn)
     599             : 
     600             : {
     601      334814 :     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       10214 : OGRGeometry *OGRFeature::StealGeometry(int iGeomField)
     650             : 
     651             : {
     652       10214 :     if (iGeomField >= 0 && iGeomField < GetGeomFieldCount())
     653             :     {
     654       10213 :         OGRGeometry *poReturn = papoGeometries[iGeomField];
     655       10213 :         papoGeometries[iGeomField] = nullptr;
     656       10213 :         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     2009080 : OGRGeometry *OGRFeature::GetGeometryRef()
     738             : 
     739             : {
     740     2009080 :     if (GetGeomFieldCount() > 0)
     741     1998020 :         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      267795 : const OGRGeometry *OGRFeature::GetGeometryRef() const
     759             : 
     760             : {
     761      267795 :     if (GetGeomFieldCount() > 0)
     762      264006 :         return GetGeomFieldRef(0);
     763             : 
     764        3789 :     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       39893 : OGRGeometryH OGR_F_GetGeometryRef(OGRFeatureH hFeat)
     784             : 
     785             : {
     786       39893 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetGeometryRef", nullptr);
     787             : 
     788       39893 :     OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
     789       39893 :     OGRGeometry *poGeom = poFeature->GetGeometryRef();
     790             : 
     791       39894 :     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       39893 :     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     3444070 : OGRGeometry *OGRFeature::GetGeomFieldRef(int iField)
     822             : 
     823             : {
     824     3444070 :     if (iField < 0 || iField >= GetGeomFieldCount())
     825           8 :         return nullptr;
     826             :     else
     827     3444060 :         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      288273 : const OGRGeometry *OGRFeature::GetGeomFieldRef(int iField) const
     841             : 
     842             : {
     843      288273 :     if (iField < 0 || iField >= GetGeomFieldCount())
     844          23 :         return nullptr;
     845             :     else
     846      288250 :         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      248096 : OGRErr OGRFeature::SetGeomField(int iField, const OGRGeometry *poGeomIn)
    1022             : 
    1023             : {
    1024      248096 :     if (iField < 0 || iField >= GetGeomFieldCount())
    1025           1 :         return OGRERR_FAILURE;
    1026             : 
    1027      248095 :     if (papoGeometries[iField] != poGeomIn)
    1028             :     {
    1029      247110 :         delete papoGeometries[iField];
    1030             : 
    1031      247110 :         if (poGeomIn != nullptr)
    1032      246986 :             papoGeometries[iField] = poGeomIn->clone();
    1033             :         else
    1034         124 :             papoGeometries[iField] = nullptr;
    1035             :     }
    1036             : 
    1037             :     // TODO(schwehr): Verify that the geometry matches the defn's type.
    1038             : 
    1039      248095 :     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     1170470 : OGRErr OGRFeature::SetGeomField(int iField,
    1095             :                                 std::unique_ptr<OGRGeometry> poGeomIn)
    1096             : 
    1097             : {
    1098     1170470 :     if (iField < 0 || iField >= GetGeomFieldCount())
    1099             :     {
    1100        5444 :         return OGRERR_FAILURE;
    1101             :     }
    1102             : 
    1103     1165020 :     if (papoGeometries[iField] != poGeomIn.get())
    1104             :     {
    1105     1164770 :         delete papoGeometries[iField];
    1106     1164770 :         papoGeometries[iField] = poGeomIn.release();
    1107             :     }
    1108             : 
    1109     1165020 :     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      346150 : OGRFeature *OGRFeature::Clone() const
    1129             : 
    1130             : {
    1131      346150 :     OGRFeature *poNew = CreateFeature(poDefn);
    1132      346150 :     if (poNew == nullptr)
    1133           0 :         return nullptr;
    1134             : 
    1135      346150 :     if (!CopySelfTo(poNew))
    1136             :     {
    1137           0 :         delete poNew;
    1138           0 :         return nullptr;
    1139             :     }
    1140             : 
    1141      346150 :     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      349846 : bool OGRFeature::CopySelfTo(OGRFeature *poNew) const
    1183             : {
    1184      349846 :     const int nFieldCount = poDefn->GetFieldCountUnsafe();
    1185     4582300 :     for (int i = 0; i < nFieldCount; i++)
    1186             :     {
    1187     4232450 :         if (!poNew->SetFieldInternal(i, pauFields + i))
    1188             :         {
    1189           0 :             return false;
    1190             :         }
    1191             :     }
    1192      349846 :     if (poNew->papoGeometries)
    1193             :     {
    1194      395372 :         for (int i = 0; i < poDefn->GetGeomFieldCount(); i++)
    1195             :         {
    1196       45526 :             if (papoGeometries[i] != nullptr)
    1197             :             {
    1198       42162 :                 poNew->papoGeometries[i] = papoGeometries[i]->clone();
    1199       42162 :                 if (poNew->papoGeometries[i] == nullptr)
    1200             :                 {
    1201           0 :                     return false;
    1202             :                 }
    1203             :             }
    1204             :         }
    1205             :     }
    1206             : 
    1207      349846 :     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      349846 :     poNew->SetFID(GetFID());
    1217             : 
    1218      349846 :     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      349846 :     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      349846 :     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      113069 : int OGR_F_GetFieldCount(OGRFeatureH hFeat)
    1271             : 
    1272             : {
    1273      113069 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldCount", 0);
    1274             : 
    1275      113069 :     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      189804 : OGRFieldDefnH OGR_F_GetFieldDefnRef(OGRFeatureH hFeat, int i)
    1312             : 
    1313             : {
    1314      189804 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldDefnRef", nullptr);
    1315             : 
    1316      189804 :     OGRFeature *poFeat = OGRFeature::FromHandle(hFeat);
    1317             : 
    1318      189804 :     return OGRFieldDefn::ToHandle(
    1319      189804 :         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      406653 : int OGRFeature::IsFieldSet(int iField) const
    1515             : 
    1516             : {
    1517      406653 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    1518      406653 :     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      405593 :         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      103195 : int OGR_F_IsFieldSet(OGRFeatureH hFeat, int iField)
    1566             : 
    1567             : {
    1568      103195 :     VALIDATE_POINTER1(hFeat, "OGR_F_IsFieldSet", 0);
    1569             : 
    1570      103195 :     const OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
    1571      103195 :     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      103195 :     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      280337 : bool OGRFeature::IsFieldNull(int iField) const
    1667             : 
    1668             : {
    1669      280337 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    1670      280337 :     if (iSpecialField >= 0)
    1671             :     {
    1672             :         // FIXME?
    1673           0 :         return false;
    1674             :     }
    1675             :     else
    1676             :     {
    1677      280337 :         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      102328 : int OGR_F_IsFieldNull(OGRFeatureH hFeat, int iField)
    1698             : 
    1699             : {
    1700      102328 :     VALIDATE_POINTER1(hFeat, "OGR_F_IsFieldNull", 0);
    1701             : 
    1702      102328 :     const OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
    1703      102328 :     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      102328 :     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      522248 : bool OGRFeature::IsFieldSetAndNotNull(int iField) const
    1728             : 
    1729             : {
    1730      522248 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    1731      522248 :     if (iSpecialField >= 0)
    1732             :     {
    1733        1060 :         return CPL_TO_BOOL(IsFieldSet(iField));
    1734             :     }
    1735             :     else
    1736             :     {
    1737      521188 :         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      173642 : int OGRFeature::GetFieldAsInteger(int iField) const
    1996             : 
    1997             : {
    1998      173642 :     int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    1999      173642 :     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      173623 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    2033             : 
    2034      173623 :     if (poFDefn == nullptr)
    2035           4 :         return 0;
    2036             : 
    2037      173619 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    2038       14119 :         return 0;
    2039             : 
    2040      159500 :     const OGRFieldType eType = poFDefn->GetType();
    2041      159500 :     if (eType == OFTInteger)
    2042             :     {
    2043      130257 :         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       29495 : GIntBig OGRFeature::GetFieldAsInteger64(int iField) const
    2139             : 
    2140             : {
    2141       29495 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    2142       29495 :     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       28694 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    2162             : 
    2163       28694 :     if (poFDefn == nullptr)
    2164           0 :         return 0;
    2165             : 
    2166       28694 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    2167          27 :         return 0;
    2168             : 
    2169       28667 :     OGRFieldType eType = poFDefn->GetType();
    2170       28667 :     if (eType == OFTInteger)
    2171             :     {
    2172       11740 :         return static_cast<GIntBig>(pauFields[iField].Integer);
    2173             :     }
    2174       16927 :     else if (eType == OFTInteger64)
    2175             :     {
    2176       16823 :         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        1503 : GIntBig OGR_F_GetFieldAsInteger64(OGRFeatureH hFeat, int iField)
    2217             : 
    2218             : {
    2219        1503 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsInteger64", 0);
    2220             : 
    2221        1503 :     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      134173 : double OGRFeature::GetFieldAsDouble(int iField) const
    2256             : 
    2257             : {
    2258      134173 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    2259      134173 :     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      134148 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    2278             : 
    2279      134148 :     if (poFDefn == nullptr)
    2280           5 :         return 0.0;
    2281             : 
    2282      134143 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    2283          96 :         return 0.0;
    2284             : 
    2285      134047 :     const OGRFieldType eType = poFDefn->GetType();
    2286      134047 :     if (eType == OFTReal)
    2287             :     {
    2288       69869 :         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        2554 : double OGR_F_GetFieldAsDouble(OGRFeatureH hFeat, int iField)
    2329             : 
    2330             : {
    2331        2554 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsDouble", 0);
    2332             : 
    2333        2554 :     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      249338 : const char *OGRFeature::GetFieldAsString(int iField) const
    2441             : 
    2442             : {
    2443      249338 :     CPLFree(m_pszTmpFieldValue);
    2444      249338 :     m_pszTmpFieldValue = nullptr;
    2445             : 
    2446      249338 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    2447      249338 :     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      249065 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    2504             : 
    2505      249065 :     if (poFDefn == nullptr)
    2506           3 :         return "";
    2507             : 
    2508      249062 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    2509        6166 :         return "";
    2510             : 
    2511      242896 :     OGRFieldType eType = poFDefn->GetType();
    2512      242896 :     if (eType == OFTString)
    2513             :     {
    2514      222705 :         if (pauFields[iField].String == nullptr)
    2515           0 :             return "";
    2516             :         else
    2517      222705 :             return pauFields[iField].String;
    2518             :     }
    2519       20191 :     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       12335 :     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       11285 :     else if (eType == OFTReal)
    2535             :     {
    2536        2676 :         char szFormat[32] = {};
    2537        2676 :         constexpr int TEMP_BUFFER_SIZE = 80;
    2538        2676 :         char szTempBuffer[TEMP_BUFFER_SIZE] = {};
    2539             : 
    2540        2676 :         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        1949 :             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        1928 :                 strcpy(szFormat, "%.15g");
    2559             : 
    2560        1928 :                 CPLsnprintf(szTempBuffer, TEMP_BUFFER_SIZE, szFormat,
    2561        1928 :                             pauFields[iField].Real);
    2562             :             }
    2563             :         }
    2564             : 
    2565        2676 :         m_pszTmpFieldValue = VSI_STRDUP_VERBOSE(szTempBuffer);
    2566        2676 :         if (m_pszTmpFieldValue == nullptr)
    2567           0 :             return "";
    2568        2676 :         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       12361 : const char *OGR_F_GetFieldAsString(OGRFeatureH hFeat, int iField)
    2757             : 
    2758             : {
    2759       12361 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsString", nullptr);
    2760             : 
    2761       12361 :     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       11369 : char **OGRFeature::GetFieldAsStringList(int iField) const
    3171             : 
    3172             : {
    3173       11369 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3174             : 
    3175       11369 :     if (poFDefn == nullptr)
    3176           0 :         return nullptr;
    3177             : 
    3178       11369 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    3179          92 :         return nullptr;
    3180             : 
    3181       11277 :     if (poFDefn->GetType() == OFTStringList)
    3182             :     {
    3183       11277 :         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     1723460 : static int OGRFeatureGetIntegerValue(const OGRFeatureDefn *poDefn,
    3469             :                                      const OGRFieldDefn *poFDefn, int nValue)
    3470             : {
    3471     1723460 :     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     1723450 :     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     1723460 :     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       15098 : char *OGRFeature::GetFieldAsSerializedJSon(int iField) const
    3517             : 
    3518             : {
    3519       15098 :     const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
    3520       15098 :     if (iSpecialField >= 0)
    3521             :     {
    3522           0 :         return nullptr;
    3523             :     }
    3524             : 
    3525       15098 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3526             : 
    3527       15098 :     if (poFDefn == nullptr)
    3528           0 :         return nullptr;
    3529             : 
    3530       15098 :     if (!IsFieldSetAndNotNullUnsafe(iField))
    3531           0 :         return nullptr;
    3532             : 
    3533       15098 :     char *pszRet = nullptr;
    3534       15098 :     OGRFieldType eType = poFDefn->GetType();
    3535       15098 :     if (eType == OFTString && poFDefn->GetSubType() == OFSTJSON)
    3536             :     {
    3537          15 :         if (pauFields[iField].String[0] != '[' &&
    3538           5 :             pauFields[iField].String[0] != '{' &&
    3539           3 :             strcmp(pauFields[iField].String, "true") != 0 &&
    3540          12 :             strcmp(pauFields[iField].String, "false") != 0 &&
    3541           2 :             CPLGetValueType(pauFields[iField].String) == CPL_VALUE_STRING)
    3542             :         {
    3543           1 :             pszRet = CPLStrdup(('"' +
    3544           2 :                                 CPLString(pauFields[iField].String)
    3545           2 :                                     .replaceAll('\\', "\\\\")
    3546           2 :                                     .replaceAll('"', "\\\"") +
    3547             :                                 '"')
    3548             :                                    .c_str());
    3549             :         }
    3550             :         else
    3551             :         {
    3552           4 :             pszRet = CPLStrdup(pauFields[iField].String);
    3553             :         }
    3554             :     }
    3555       15093 :     else if (eType == OFTStringList)
    3556             :     {
    3557        5031 :         char **papszValues = GetFieldAsStringList(iField);
    3558        5031 :         if (papszValues == nullptr)
    3559             :         {
    3560           1 :             pszRet = CPLStrdup("[]");
    3561             :         }
    3562             :         else
    3563             :         {
    3564        5030 :             json_object *poObj = json_object_new_array();
    3565       15091 :             for (int i = 0; papszValues[i] != nullptr; i++)
    3566             :             {
    3567       10061 :                 json_object_array_add(poObj,
    3568       10061 :                                       json_object_new_string(papszValues[i]));
    3569             :             }
    3570        5030 :             pszRet = CPLStrdup(json_object_to_json_string(poObj));
    3571        5030 :             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       15098 :     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     1651900 : void OGRFeature::SetField(int iField, int nValue)
    3666             : 
    3667             : {
    3668     1651900 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3669             : 
    3670     1651900 :     if (poFDefn == nullptr)
    3671           0 :         return;
    3672             : 
    3673     1651900 :     OGRFieldType eType = poFDefn->GetType();
    3674     1651900 :     if (eType == OFTInteger)
    3675             :     {
    3676     3297640 :         pauFields[iField].Integer =
    3677     1648820 :             OGRFeatureGetIntegerValue(poDefn, poFDefn, nValue);
    3678     1648820 :         pauFields[iField].Set.nMarker2 = 0;
    3679     1648820 :         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        4815 : void OGR_F_SetFieldInteger(OGRFeatureH hFeat, int iField, int nValue)
    3758             : 
    3759             : {
    3760        4815 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldInteger");
    3761             : 
    3762        4815 :     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       96299 : void OGRFeature::SetField(int iField, GIntBig nValue)
    3806             : 
    3807             : {
    3808       96299 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3809             : 
    3810       96299 :     if (poFDefn == nullptr)
    3811           0 :         return;
    3812             : 
    3813       96299 :     OGRFieldType eType = poFDefn->GetType();
    3814       96299 :     if (eType == OFTInteger)
    3815             :     {
    3816      175680 :         const int nVal32 = nValue < INT_MIN   ? INT_MIN
    3817       87840 :                            : nValue > INT_MAX ? INT_MAX
    3818             :                                               : static_cast<int>(nValue);
    3819             : 
    3820       87840 :         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       87840 :         SetField(iField, nVal32);
    3830             :     }
    3831        8459 :     else if (eType == OFTInteger64)
    3832             :     {
    3833        7691 :         pauFields[iField].Integer64 = nValue;
    3834             :     }
    3835         768 :     else if (eType == OFTReal)
    3836             :     {
    3837         648 :         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        1296 :         if (pauFields[iField].Real >=
    3842        1294 :                 static_cast<double>(std::numeric_limits<int64_t>::max()) ||
    3843         646 :             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       85737 : void OGR_F_SetFieldInteger64(OGRFeatureH hFeat, int iField, GIntBig nValue)
    3933             : 
    3934             : {
    3935       85737 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldInteger64");
    3936             : 
    3937       85737 :     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       71475 : void OGRFeature::SetField(int iField, double dfValue)
    3982             : 
    3983             : {
    3984       71475 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    3985             : 
    3986       71475 :     if (poFDefn == nullptr)
    3987           0 :         return;
    3988             : 
    3989       71475 :     const OGRFieldType eType = poFDefn->GetType();
    3990       71475 :     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       57564 :         pauFields[iField].Real = dfValue;
    4001             :     }
    4002       13911 :     else if (eType == OFTInteger)
    4003             :     {
    4004       13473 :         constexpr int nMin = std::numeric_limits<int>::min();
    4005       13473 :         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       13471 :             constexpr int nMax = std::numeric_limits<int>::max();
    4017       26942 :             const int nVal = dfValue < nMin   ? nMin
    4018       13471 :                              : dfValue > nMax ? nMax
    4019       13462 :                                               : static_cast<int>(dfValue);
    4020       26942 :             pauFields[iField].Integer =
    4021       13471 :                 OGRFeatureGetIntegerValue(poDefn, poFDefn, nVal);
    4022       13471 :             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       13473 :         pauFields[iField].Set.nMarker2 = 0;
    4032       13473 :         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        2130 : void OGR_F_SetFieldDouble(OGRFeatureH hFeat, int iField, double dfValue)
    4133             : 
    4134             : {
    4135        2130 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDouble");
    4136             : 
    4137        2130 :     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     2388290 : void OGRFeature::SetField(int iField, const char *pszValue)
    4182             : 
    4183             : {
    4184             :     static int bWarn = -1;
    4185     2388290 :     if (bWarn < 0)
    4186         396 :         bWarn = CPLTestBool(
    4187             :             CPLGetConfigOption("OGR_SETFIELD_NUMERIC_WARNING", "YES"));
    4188             : 
    4189     2388290 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    4190     2388290 :     if (poFDefn == nullptr)
    4191           1 :         return;
    4192             : 
    4193     2388280 :     char *pszLast = nullptr;
    4194             : 
    4195     2388280 :     OGRFieldType eType = poFDefn->GetType();
    4196     2388280 :     if (eType == OFTString)
    4197             :     {
    4198     2142360 :         if (IsFieldSetAndNotNullUnsafe(iField))
    4199        4444 :             CPLFree(pauFields[iField].String);
    4200             : 
    4201     2142360 :         pauFields[iField].String = VSI_STRDUP_VERBOSE(pszValue ? pszValue : "");
    4202     2142360 :         if (pauFields[iField].String == nullptr)
    4203             :         {
    4204           0 :             OGR_RawField_SetUnset(&pauFields[iField]);
    4205             :         }
    4206             :     }
    4207      245924 :     else if (eType == OFTInteger)
    4208             :     {
    4209       46102 :         if (poFDefn->GetSubType() == OFSTBoolean)
    4210             :         {
    4211         100 :             constexpr char DIGIT_ZERO = '0';
    4212         100 :             if ((pszValue[0] == '1' && pszValue[1] == '\0') ||
    4213          16 :                 EQUAL(pszValue, "true") || EQUAL(pszValue, "on") ||
    4214          12 :                 EQUAL(pszValue, "yes"))
    4215             :             {
    4216          89 :                 pauFields[iField].Integer = 1;
    4217          89 :                 pauFields[iField].Set.nMarker2 = 0;
    4218          89 :                 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       46002 :             errno = 0;
    4258             : 
    4259       46002 :             long long nVal64 = std::strtoll(pszValue, &pszLast, 10);
    4260       91989 :             int nVal32 = nVal64 > INT_MAX   ? INT_MAX
    4261       45987 :                          : nVal64 < INT_MIN ? INT_MIN
    4262             :                                             : static_cast<int>(nVal64);
    4263       92004 :             pauFields[iField].Integer =
    4264       46002 :                 OGRFeatureGetIntegerValue(poDefn, poFDefn, nVal32);
    4265       46002 :             if (bWarn && pauFields[iField].Integer == nVal32 &&
    4266       46002 :                 (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       46002 :             pauFields[iField].Set.nMarker2 = 0;
    4273       46002 :             pauFields[iField].Set.nMarker3 = 0;
    4274             :         }
    4275             :     }
    4276      199822 :     else if (eType == OFTInteger64)
    4277             :     {
    4278       93863 :         pauFields[iField].Integer64 = CPLAtoGIntBigEx(pszValue, bWarn, nullptr);
    4279       93863 :         pauFields[iField].Set.nMarker3 = 0;
    4280             :     }
    4281      105959 :     else if (eType == OFTReal)
    4282             :     {
    4283       93731 :         pauFields[iField].Real = CPLStrtod(pszValue, &pszLast);
    4284       93731 :         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             : /*                        OGR_F_SetFieldString()                        */
    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 function is the same as the C++ method OGRFeature::SetField().
    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 hFeat handle to the feature that owned the field.
    4488             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    4489             :  * @param pszValue the value to assign.
    4490             :  */
    4491             : 
    4492       12336 : void OGR_F_SetFieldString(OGRFeatureH hFeat, int iField, const char *pszValue)
    4493             : 
    4494             : {
    4495       12336 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldString");
    4496             : 
    4497       12336 :     OGRFeature::FromHandle(hFeat)->SetField(iField, pszValue);
    4498             : }
    4499             : 
    4500             : /************************************************************************/
    4501             : /*                              SetField()                              */
    4502             : /************************************************************************/
    4503             : 
    4504             : /**
    4505             :  * \fn OGRFeature::SetField( const char* pszFName, int nCount, const int
    4506             :  * *panValues ) \brief Set field to list of integers value.
    4507             :  *
    4508             :  * This method currently on has an effect of OFTIntegerList, OFTInteger64List
    4509             :  * and OFTRealList fields.
    4510             :  *
    4511             :  * @note This method has only an effect on the in-memory feature object. If
    4512             :  * this object comes from a layer and the modifications must be serialized back
    4513             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4514             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4515             :  *
    4516             :  * @param pszFName the name of the field to set.
    4517             :  * @param nCount the number of values in the list being assigned.
    4518             :  * @param panValues the values to assign.
    4519             :  */
    4520             : 
    4521             : /**
    4522             :  * \brief Set field to list of integers value.
    4523             :  *
    4524             :  * This method currently on has an effect of OFTIntegerList, OFTInteger64List
    4525             :  * and OFTRealList fields.
    4526             :  *
    4527             :  * This method is the same as the C function OGR_F_SetFieldIntegerList().
    4528             :  *
    4529             :  * @note This method has only an effect on the in-memory feature object. If
    4530             :  * this object comes from a layer and the modifications must be serialized back
    4531             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4532             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4533             :  *
    4534             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4535             :  * @param nCount the number of values in the list being assigned.
    4536             :  * @param panValues the values to assign.
    4537             :  */
    4538             : 
    4539       32608 : void OGRFeature::SetField(int iField, int nCount, const int *panValues)
    4540             : 
    4541             : {
    4542       32608 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    4543             : 
    4544       32608 :     if (poFDefn == nullptr)
    4545           0 :         return;
    4546             : 
    4547       32608 :     OGRFieldType eType = poFDefn->GetType();
    4548       32608 :     if (eType == OFTIntegerList)
    4549             :     {
    4550             :         OGRField uField;
    4551       32598 :         int *panValuesMod = nullptr;
    4552             : 
    4553       57930 :         if (poFDefn->GetSubType() == OFSTBoolean ||
    4554       25332 :             poFDefn->GetSubType() == OFSTInt16)
    4555             :         {
    4556       21654 :             for (int i = 0; i < nCount; i++)
    4557             :             {
    4558             :                 int nVal =
    4559       13966 :                     OGRFeatureGetIntegerValue(poDefn, poFDefn, panValues[i]);
    4560       13966 :                 if (panValues[i] != nVal)
    4561             :                 {
    4562           2 :                     if (panValuesMod == nullptr)
    4563             :                     {
    4564             :                         panValuesMod = static_cast<int *>(
    4565           2 :                             VSI_MALLOC_VERBOSE(nCount * sizeof(int)));
    4566           2 :                         if (panValuesMod == nullptr)
    4567           0 :                             return;
    4568           2 :                         if (nCount > 0)
    4569           2 :                             memcpy(panValuesMod, panValues,
    4570           2 :                                    nCount * sizeof(int));
    4571             :                     }
    4572           2 :                     panValuesMod[i] = nVal;
    4573             :                 }
    4574             :             }
    4575             :         }
    4576             : 
    4577       32598 :         uField.IntegerList.nCount = nCount;
    4578       32598 :         uField.Set.nMarker2 = 0;
    4579       32598 :         uField.Set.nMarker3 = 0;
    4580       32598 :         uField.IntegerList.paList =
    4581       32598 :             panValuesMod ? panValuesMod : const_cast<int *>(panValues);
    4582             : 
    4583       32598 :         SetField(iField, &uField);
    4584       32598 :         CPLFree(panValuesMod);
    4585             :     }
    4586          10 :     else if (eType == OFTInteger64List)
    4587             :     {
    4588           2 :         std::vector<GIntBig> anValues;
    4589           1 :         anValues.reserve(nCount);
    4590           4 :         for (int i = 0; i < nCount; i++)
    4591           3 :             anValues.push_back(panValues[i]);
    4592           1 :         if (nCount > 0)
    4593           1 :             SetField(iField, nCount, &anValues[0]);
    4594             :     }
    4595           9 :     else if (eType == OFTRealList)
    4596             :     {
    4597           2 :         std::vector<double> adfValues;
    4598           1 :         adfValues.reserve(nCount);
    4599           4 :         for (int i = 0; i < nCount; i++)
    4600           3 :             adfValues.push_back(static_cast<double>(panValues[i]));
    4601           1 :         if (nCount > 0)
    4602           1 :             SetField(iField, nCount, &adfValues[0]);
    4603             :     }
    4604           8 :     else if ((eType == OFTInteger || eType == OFTInteger64 ||
    4605           3 :               eType == OFTReal) &&
    4606             :              nCount == 1)
    4607             :     {
    4608           3 :         SetField(iField, panValues[0]);
    4609             :     }
    4610           5 :     else if (eType == OFTStringList)
    4611             :     {
    4612             :         char **papszValues = static_cast<char **>(
    4613           1 :             VSI_MALLOC_VERBOSE((nCount + 1) * sizeof(char *)));
    4614           1 :         if (papszValues == nullptr)
    4615           0 :             return;
    4616           4 :         for (int i = 0; i < nCount; i++)
    4617           3 :             papszValues[i] = VSI_STRDUP_VERBOSE(CPLSPrintf("%d", panValues[i]));
    4618           1 :         papszValues[nCount] = nullptr;
    4619           1 :         SetField(iField, papszValues);
    4620           1 :         CSLDestroy(papszValues);
    4621             :     }
    4622             : }
    4623             : 
    4624             : /************************************************************************/
    4625             : /*                     OGR_F_SetFieldIntegerList()                      */
    4626             : /************************************************************************/
    4627             : 
    4628             : /**
    4629             :  * \brief Set field to list of integers value.
    4630             :  *
    4631             :  * This function currently on has an effect of OFTIntegerList, OFTInteger64List
    4632             :  * and OFTRealList fields.
    4633             :  *
    4634             :  * This function is the same as the C++ method OGRFeature::SetField().
    4635             :  *
    4636             :  * @note This method has only an effect on the in-memory feature object. If
    4637             :  * this object comes from a layer and the modifications must be serialized back
    4638             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4639             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4640             :  *
    4641             :  * @param hFeat handle to the feature that owned the field.
    4642             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4643             :  * @param nCount the number of values in the list being assigned.
    4644             :  * @param panValues the values to assign.
    4645             :  */
    4646             : 
    4647           9 : void OGR_F_SetFieldIntegerList(OGRFeatureH hFeat, int iField, int nCount,
    4648             :                                const int *panValues)
    4649             : 
    4650             : {
    4651           9 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldIntegerList");
    4652             : 
    4653           9 :     OGRFeature::FromHandle(hFeat)->SetField(iField, nCount, panValues);
    4654             : }
    4655             : 
    4656             : /************************************************************************/
    4657             : /*                              SetField()                              */
    4658             : /************************************************************************/
    4659             : 
    4660             : /**
    4661             :  * \fn OGRFeature::SetField( const char* pszFName, int nCount, const GIntBig
    4662             :  * *panValues )
    4663             :  * \brief Set field to list of 64 bit integers value.
    4664             :  *
    4665             :  * This method currently on has an effect of OFTIntegerList, OFTInteger64List
    4666             :  * and OFTRealList fields.
    4667             :  *
    4668             :  * @note This method has only an effect on the in-memory feature object. If
    4669             :  * this object comes from a layer and the modifications must be serialized back
    4670             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4671             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4672             :  *
    4673             :  * @param pszFName the name of the field to set.
    4674             :  * @param nCount the number of values in the list being assigned.
    4675             :  * @param panValues the values to assign.
    4676             :  */
    4677             : 
    4678             : /**
    4679             :  * \brief Set field to list of 64 bit integers value.
    4680             :  *
    4681             :  * This method currently on has an effect of OFTIntegerList, OFTInteger64List
    4682             :  * and OFTRealList fields.
    4683             :  *
    4684             :  * This method is the same as the C function OGR_F_SetFieldInteger64List().
    4685             :  *
    4686             :  * @note This method has only an effect on the in-memory feature object. If
    4687             :  * this object comes from a layer and the modifications must be serialized back
    4688             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4689             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4690             :  *
    4691             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4692             :  * @param nCount the number of values in the list being assigned.
    4693             :  * @param panValues the values to assign.
    4694             :  */
    4695             : 
    4696       12864 : void OGRFeature::SetField(int iField, int nCount, const GIntBig *panValues)
    4697             : 
    4698             : {
    4699       12864 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    4700             : 
    4701       12864 :     if (poFDefn == nullptr)
    4702           0 :         return;
    4703             : 
    4704       12864 :     OGRFieldType eType = poFDefn->GetType();
    4705       12864 :     if (eType == OFTIntegerList)
    4706             :     {
    4707         150 :         std::vector<int> anValues;
    4708             : 
    4709         406 :         for (int i = 0; i < nCount; i++)
    4710             :         {
    4711         331 :             const GIntBig nValue = panValues[i];
    4712         662 :             const int nVal32 = nValue < INT_MIN   ? INT_MIN
    4713         331 :                                : nValue > INT_MAX ? INT_MAX
    4714             :                                                   : static_cast<int>(nValue);
    4715             : 
    4716         331 :             if (nVal32 != nValue)
    4717             :             {
    4718           2 :                 CPLError(
    4719             :                     CE_Warning, CPLE_AppDefined,
    4720             :                     "Field %s.%s: Integer overflow occurred when trying to "
    4721             :                     "set %" PRId64 " as 32 bit value.",
    4722           1 :                     poDefn->GetName(), poFDefn->GetNameRef(),
    4723             :                     static_cast<int64_t>(nValue));
    4724             :             }
    4725         331 :             anValues.push_back(nVal32);
    4726             :         }
    4727          75 :         if (nCount > 0)
    4728          75 :             SetField(iField, nCount, &anValues[0]);
    4729             :     }
    4730       12789 :     else if (eType == OFTInteger64List)
    4731             :     {
    4732             :         OGRField uField;
    4733       12779 :         uField.Integer64List.nCount = nCount;
    4734       12779 :         uField.Set.nMarker2 = 0;
    4735       12779 :         uField.Set.nMarker3 = 0;
    4736       12779 :         uField.Integer64List.paList = const_cast<GIntBig *>(panValues);
    4737             : 
    4738       12779 :         SetField(iField, &uField);
    4739             :     }
    4740          10 :     else if (eType == OFTRealList)
    4741             :     {
    4742           4 :         std::vector<double> adfValues;
    4743           2 :         adfValues.reserve(nCount);
    4744         103 :         for (int i = 0; i < nCount; i++)
    4745         101 :             adfValues.push_back(static_cast<double>(panValues[i]));
    4746           2 :         if (nCount > 0)
    4747           2 :             SetField(iField, nCount, &adfValues[0]);
    4748             :     }
    4749           8 :     else if ((eType == OFTInteger || eType == OFTInteger64 ||
    4750           3 :               eType == OFTReal) &&
    4751             :              nCount == 1)
    4752             :     {
    4753           3 :         SetField(iField, panValues[0]);
    4754             :     }
    4755           5 :     else if (eType == OFTStringList)
    4756             :     {
    4757             :         char **papszValues = static_cast<char **>(
    4758           1 :             VSI_MALLOC_VERBOSE((nCount + 1) * sizeof(char *)));
    4759           1 :         if (papszValues == nullptr)
    4760           0 :             return;
    4761           2 :         for (int i = 0; i < nCount; i++)
    4762           2 :             papszValues[i] =
    4763           1 :                 VSI_STRDUP_VERBOSE(CPLSPrintf(CPL_FRMT_GIB, panValues[i]));
    4764           1 :         papszValues[nCount] = nullptr;
    4765           1 :         SetField(iField, papszValues);
    4766           1 :         CSLDestroy(papszValues);
    4767             :     }
    4768             : }
    4769             : 
    4770             : /************************************************************************/
    4771             : /*                    OGR_F_SetFieldInteger64List()                     */
    4772             : /************************************************************************/
    4773             : 
    4774             : /**
    4775             :  * \brief Set field to list of 64 bit integers value.
    4776             :  *
    4777             :  * This function currently on has an effect of OFTIntegerList, OFTInteger64List
    4778             :  * and OFTRealList fields.
    4779             :  *
    4780             :  * This function is the same as the C++ method OGRFeature::SetField().
    4781             :  *
    4782             :  * @note This method has only an effect on the in-memory feature object. If
    4783             :  * this object comes from a layer and the modifications must be serialized back
    4784             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4785             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4786             :  *
    4787             :  * @param hFeat handle to the feature that owned the field.
    4788             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4789             :  * @param nCount the number of values in the list being assigned.
    4790             :  * @param panValues the values to assign.
    4791             :  */
    4792             : 
    4793         124 : void OGR_F_SetFieldInteger64List(OGRFeatureH hFeat, int iField, int nCount,
    4794             :                                  const GIntBig *panValues)
    4795             : 
    4796             : {
    4797         124 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldInteger64List");
    4798             : 
    4799         124 :     OGRFeature::FromHandle(hFeat)->SetField(iField, nCount, panValues);
    4800             : }
    4801             : 
    4802             : /************************************************************************/
    4803             : /*                              SetField()                              */
    4804             : /************************************************************************/
    4805             : 
    4806             : /**
    4807             :  * \fn OGRFeature::SetField( const char* pszFName, int nCount, const double *
    4808             :  * padfValues ) \brief Set field to list of doubles value.
    4809             :  *
    4810             :  * This method currently on has an effect of OFTIntegerList, OFTInteger64List,
    4811             :  * OFTRealList fields.
    4812             :  *
    4813             :  * @note This method has only an effect on the in-memory feature object. If
    4814             :  * this object comes from a layer and the modifications must be serialized back
    4815             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4816             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4817             :  *
    4818             :  * @param pszFName the name of the field to set.
    4819             :  * @param nCount the number of values in the list being assigned.
    4820             :  * @param padfValues the values to assign.
    4821             :  */
    4822             : 
    4823             : /**
    4824             :  * \brief Set field to list of doubles value.
    4825             :  *
    4826             :  * This method currently on has an effect of OFTIntegerList, OFTInteger64List,
    4827             :  * OFTRealList fields.
    4828             :  *
    4829             :  * This method is the same as the C function OGR_F_SetFieldDoubleList().
    4830             :  *
    4831             :  * @note This method has only an effect on the in-memory feature object. If
    4832             :  * this object comes from a layer and the modifications must be serialized back
    4833             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4834             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4835             :  *
    4836             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4837             :  * @param nCount the number of values in the list being assigned.
    4838             :  * @param padfValues the values to assign.
    4839             :  */
    4840             : 
    4841       21127 : void OGRFeature::SetField(int iField, int nCount, const double *padfValues)
    4842             : 
    4843             : {
    4844       21127 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    4845             : 
    4846       21127 :     if (poFDefn == nullptr)
    4847           0 :         return;
    4848             : 
    4849       21127 :     OGRFieldType eType = poFDefn->GetType();
    4850       21127 :     if (eType == OFTRealList)
    4851             :     {
    4852             :         OGRField uField;
    4853             : 
    4854       20870 :         uField.RealList.nCount = nCount;
    4855       20870 :         uField.Set.nMarker2 = 0;
    4856       20870 :         uField.Set.nMarker3 = 0;
    4857       20870 :         uField.RealList.paList = const_cast<double *>(padfValues);
    4858             : 
    4859       20870 :         SetField(iField, &uField);
    4860             :     }
    4861         257 :     else if (eType == OFTIntegerList)
    4862             :     {
    4863         366 :         std::vector<int> anValues;
    4864         183 :         anValues.reserve(nCount);
    4865         507 :         for (int i = 0; i < nCount; i++)
    4866         324 :             anValues.push_back(static_cast<int>(padfValues[i]));
    4867             : 
    4868         183 :         if (nCount > 0)
    4869         183 :             SetField(iField, nCount, &anValues[0]);
    4870             :     }
    4871          74 :     else if (eType == OFTInteger64List)
    4872             :     {
    4873           4 :         std::vector<GIntBig> anValues;
    4874           2 :         anValues.reserve(nCount);
    4875           5 :         for (int i = 0; i < nCount; i++)
    4876           3 :             anValues.push_back(static_cast<GIntBig>(padfValues[i]));
    4877           2 :         if (nCount > 0)
    4878           2 :             SetField(iField, nCount, &anValues[0]);
    4879             :     }
    4880          72 :     else if ((eType == OFTInteger || eType == OFTInteger64 ||
    4881          67 :               eType == OFTReal) &&
    4882             :              nCount == 1)
    4883             :     {
    4884          67 :         SetField(iField, padfValues[0]);
    4885             :     }
    4886           5 :     else if (eType == OFTStringList)
    4887             :     {
    4888             :         char **papszValues = static_cast<char **>(
    4889           1 :             VSI_MALLOC_VERBOSE((nCount + 1) * sizeof(char *)));
    4890           1 :         if (papszValues == nullptr)
    4891           0 :             return;
    4892           3 :         for (int i = 0; i < nCount; i++)
    4893           4 :             papszValues[i] =
    4894           2 :                 VSI_STRDUP_VERBOSE(CPLSPrintf("%.16g", padfValues[i]));
    4895           1 :         papszValues[nCount] = nullptr;
    4896           1 :         SetField(iField, papszValues);
    4897           1 :         CSLDestroy(papszValues);
    4898             :     }
    4899             : }
    4900             : 
    4901             : /************************************************************************/
    4902             : /*                      OGR_F_SetFieldDoubleList()                      */
    4903             : /************************************************************************/
    4904             : 
    4905             : /**
    4906             :  * \brief Set field to list of doubles value.
    4907             :  *
    4908             :  * This function currently on has an effect of OFTIntegerList, OFTInteger64List,
    4909             :  * OFTRealList fields.
    4910             :  *
    4911             :  * This function is the same as the C++ method OGRFeature::SetField().
    4912             :  *
    4913             :  * @note This method has only an effect on the in-memory feature object. If
    4914             :  * this object comes from a layer and the modifications must be serialized back
    4915             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4916             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4917             :  *
    4918             :  * @param hFeat handle to the feature that owned the field.
    4919             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4920             :  * @param nCount the number of values in the list being assigned.
    4921             :  * @param padfValues the values to assign.
    4922             :  */
    4923             : 
    4924          91 : void OGR_F_SetFieldDoubleList(OGRFeatureH hFeat, int iField, int nCount,
    4925             :                               const double *padfValues)
    4926             : 
    4927             : {
    4928          91 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDoubleList");
    4929             : 
    4930          91 :     OGRFeature::FromHandle(hFeat)->SetField(iField, nCount, padfValues);
    4931             : }
    4932             : 
    4933             : /************************************************************************/
    4934             : /*                              SetField()                              */
    4935             : /************************************************************************/
    4936             : 
    4937             : /**
    4938             :  * \fn OGRFeature::SetField( const char* pszFName,  const char * const *
    4939             :  * papszValues ) \brief Set field to list of strings value.
    4940             :  *
    4941             :  * This method currently on has an effect of OFTStringList fields.
    4942             :  *
    4943             :  * @note This method has only an effect on the in-memory feature object. If
    4944             :  * this object comes from a layer and the modifications must be serialized back
    4945             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4946             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4947             :  *
    4948             :  * @param pszFName the name of the field to set.
    4949             :  * @param papszValues the values to assign. List of NUL-terminated string,
    4950             :  * ending with a NULL pointer.
    4951             :  */
    4952             : 
    4953             : /**
    4954             :  * \brief Set field to list of strings value.
    4955             :  *
    4956             :  * This method currently on has an effect of OFTStringList fields.
    4957             :  *
    4958             :  * This method is the same as the C function OGR_F_SetFieldStringList().
    4959             :  *
    4960             :  * @note This method has only an effect on the in-memory feature object. If
    4961             :  * this object comes from a layer and the modifications must be serialized back
    4962             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    4963             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    4964             :  *
    4965             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    4966             :  * @param papszValues the values to assign. List of NUL-terminated string,
    4967             :  * ending with a NULL pointer.
    4968             :  */
    4969             : 
    4970       37805 : void OGRFeature::SetField(int iField, const char *const *papszValues)
    4971             : 
    4972             : {
    4973       37805 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    4974             : 
    4975       37805 :     if (poFDefn == nullptr)
    4976           0 :         return;
    4977             : 
    4978       37805 :     OGRFieldType eType = poFDefn->GetType();
    4979       37805 :     if (eType == OFTStringList)
    4980             :     {
    4981       24569 :         if (!IsFieldSetAndNotNullUnsafe(iField) ||
    4982        5629 :             papszValues != pauFields[iField].StringList.paList)
    4983             :         {
    4984             :             OGRField uField;
    4985             : 
    4986       18938 :             uField.StringList.nCount = CSLCount(papszValues);
    4987       18938 :             uField.Set.nMarker2 = 0;
    4988       18938 :             uField.Set.nMarker3 = 0;
    4989       18938 :             uField.StringList.paList = const_cast<char **>(papszValues);
    4990             : 
    4991       18938 :             SetField(iField, &uField);
    4992             :         }
    4993             :     }
    4994       18865 :     else if (eType == OFTIntegerList)
    4995             :     {
    4996        9845 :         const int nValues = CSLCount(papszValues);
    4997             :         int *panValues =
    4998        9845 :             static_cast<int *>(VSI_MALLOC_VERBOSE(nValues * sizeof(int)));
    4999        9845 :         if (panValues == nullptr)
    5000           0 :             return;
    5001       28447 :         for (int i = 0; i < nValues; i++)
    5002             :         {
    5003             :             // As allowed by C standard, some systems like MSVC do not
    5004             :             // reset errno.
    5005       18602 :             errno = 0;
    5006             : 
    5007       18602 :             int nVal = atoi(papszValues[i]);
    5008       18602 :             if (errno == ERANGE)
    5009             :             {
    5010           0 :                 CPLError(
    5011             :                     CE_Warning, CPLE_AppDefined,
    5012             :                     "Field %s.%s: 32 bit integer overflow when converting %s",
    5013           0 :                     poDefn->GetName(), poFDefn->GetNameRef(), papszValues[i]);
    5014           0 :                 if (papszValues[i][0] == '-')
    5015           0 :                     nVal = INT_MIN;
    5016             :                 else
    5017           0 :                     nVal = INT_MAX;
    5018             :             }
    5019       18602 :             panValues[i] = nVal;
    5020             :         }
    5021        9845 :         SetField(iField, nValues, panValues);
    5022        9845 :         CPLFree(panValues);
    5023             :     }
    5024        9020 :     else if (eType == OFTInteger64List)
    5025             :     {
    5026        3377 :         const int nValues = CSLCount(papszValues);
    5027             :         GIntBig *panValues = static_cast<GIntBig *>(
    5028        3377 :             VSI_MALLOC_VERBOSE(nValues * sizeof(GIntBig)));
    5029        3377 :         if (panValues == nullptr)
    5030           0 :             return;
    5031       10073 :         for (int i = 0; i < nValues; i++)
    5032             :         {
    5033        6696 :             panValues[i] = CPLAtoGIntBigEx(papszValues[i], TRUE, nullptr);
    5034             :         }
    5035        3377 :         SetField(iField, nValues, panValues);
    5036        3377 :         CPLFree(panValues);
    5037             :     }
    5038        5643 :     else if (eType == OFTRealList)
    5039             :     {
    5040        5643 :         const int nValues = CSLCount(papszValues);
    5041             :         double *padfValues =
    5042        5643 :             static_cast<double *>(VSI_MALLOC_VERBOSE(nValues * sizeof(double)));
    5043        5643 :         if (padfValues == nullptr)
    5044           0 :             return;
    5045       15738 :         for (int i = 0; i < nValues; i++)
    5046             :         {
    5047       10095 :             padfValues[i] = CPLAtof(papszValues[i]);
    5048             :         }
    5049        5643 :         SetField(iField, nValues, padfValues);
    5050        5643 :         CPLFree(padfValues);
    5051             :     }
    5052             : }
    5053             : 
    5054             : /************************************************************************/
    5055             : /*                      OGR_F_SetFieldStringList()                      */
    5056             : /************************************************************************/
    5057             : 
    5058             : /**
    5059             :  * \brief Set field to list of strings value.
    5060             :  *
    5061             :  * This function currently on has an effect of OFTStringList fields.
    5062             :  *
    5063             :  * This function is the same as the C++ method OGRFeature::SetField().
    5064             :  *
    5065             :  * @note This method has only an effect on the in-memory feature object. If
    5066             :  * this object comes from a layer and the modifications must be serialized back
    5067             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5068             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5069             :  *
    5070             :  * @param hFeat handle to the feature that owned the field.
    5071             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    5072             :  * @param papszValues the values to assign. List of NUL-terminated string,
    5073             :  * ending with a NULL pointer.
    5074             :  */
    5075             : 
    5076          43 : void OGR_F_SetFieldStringList(OGRFeatureH hFeat, int iField,
    5077             :                               CSLConstList papszValues)
    5078             : 
    5079             : {
    5080          43 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldStringList");
    5081             : 
    5082          43 :     OGRFeature::FromHandle(hFeat)->SetField(iField, papszValues);
    5083             : }
    5084             : 
    5085             : /************************************************************************/
    5086             : /*                              SetField()                              */
    5087             : /************************************************************************/
    5088             : 
    5089             : /**
    5090             :  * \brief Set field to binary data.
    5091             :  *
    5092             :  * This method currently on has an effect of OFTBinary fields.
    5093             :  *
    5094             :  * This method is the same as the C function OGR_F_SetFieldBinary().
    5095             :  *
    5096             :  * @note This method has only an effect on the in-memory feature object. If
    5097             :  * this object comes from a layer and the modifications must be serialized back
    5098             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5099             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5100             :  *
    5101             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    5102             :  * @param nBytes bytes of data being set.
    5103             :  * @param pabyData the raw data being applied.
    5104             :  */
    5105             : 
    5106       18017 : void OGRFeature::SetField(int iField, int nBytes, const void *pabyData)
    5107             : 
    5108             : {
    5109       18017 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    5110             : 
    5111       18017 :     if (poFDefn == nullptr)
    5112           0 :         return;
    5113             : 
    5114       18017 :     OGRFieldType eType = poFDefn->GetType();
    5115       18017 :     if (eType == OFTBinary)
    5116             :     {
    5117             :         OGRField uField;
    5118             : 
    5119       18014 :         uField.Binary.nCount = nBytes;
    5120       18014 :         uField.Set.nMarker2 = 0;
    5121       18014 :         uField.Set.nMarker3 = 0;
    5122       18014 :         uField.Binary.paData =
    5123             :             const_cast<GByte *>(static_cast<const GByte *>(pabyData));
    5124             : 
    5125       18014 :         SetField(iField, &uField);
    5126             :     }
    5127           3 :     else if (eType == OFTString || eType == OFTStringList)
    5128             :     {
    5129           3 :         char *pszStr = static_cast<char *>(VSI_MALLOC_VERBOSE(nBytes + 1));
    5130           3 :         if (pszStr == nullptr)
    5131           0 :             return;
    5132           3 :         if (nBytes > 0)
    5133           3 :             memcpy(pszStr, pabyData, nBytes);
    5134           3 :         pszStr[nBytes] = 0;
    5135           3 :         SetField(iField, pszStr);
    5136           3 :         CPLFree(pszStr);
    5137             :     }
    5138             : }
    5139             : 
    5140             : /************************************************************************/
    5141             : /*                        OGR_F_SetFieldBinary()                        */
    5142             : /************************************************************************/
    5143             : 
    5144             : /**
    5145             :  * \brief Set field to binary data.
    5146             :  *
    5147             :  * This function currently on has an effect of OFTBinary fields.
    5148             :  *
    5149             :  * This function is the same as the C++ method OGRFeature::SetField().
    5150             :  *
    5151             :  * @note This method has only an effect on the in-memory feature object. If
    5152             :  * this object comes from a layer and the modifications must be serialized back
    5153             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5154             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5155             :  *
    5156             :  * @param hFeat handle to the feature that owned the field.
    5157             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    5158             :  * @param nBytes the number of bytes in pabyData array.
    5159             :  * @param pabyData the data to apply.
    5160             :  */
    5161             : 
    5162         524 : void OGR_F_SetFieldBinary(OGRFeatureH hFeat, int iField, int nBytes,
    5163             :                           const void *pabyData)
    5164             : 
    5165             : {
    5166         524 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldBinary");
    5167             : 
    5168         524 :     OGRFeature::FromHandle(hFeat)->SetField(iField, nBytes, pabyData);
    5169             : }
    5170             : 
    5171             : /************************************************************************/
    5172             : /*                              SetField()                              */
    5173             : /************************************************************************/
    5174             : 
    5175             : /**
    5176             :  * \fn OGRFeature::SetField( const char* pszFName, int nYear, int nMonth,
    5177             :  *                           int nDay, int nHour, int nMinute, float fSecond,
    5178             :  *                           int nTZFlag )
    5179             :  * \brief Set field to date.
    5180             :  *
    5181             :  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
    5182             :  * fields.
    5183             :  *
    5184             :  * @note This method has only an effect on the in-memory feature object. If
    5185             :  * this object comes from a layer and the modifications must be serialized back
    5186             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5187             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5188             :  *
    5189             :  * @param pszFName the name of the field to set.
    5190             :  * @param nYear (including century)
    5191             :  * @param nMonth (1-12)
    5192             :  * @param nDay (1-31)
    5193             :  * @param nHour (0-23)
    5194             :  * @param nMinute (0-59)
    5195             :  * @param fSecond (0-59, with millisecond accuracy)
    5196             :  * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
    5197             :  */
    5198             : 
    5199             : /**
    5200             :  * \brief Set field to date.
    5201             :  *
    5202             :  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
    5203             :  * fields.
    5204             :  *
    5205             :  * This method is the same as the C function OGR_F_SetFieldDateTime().
    5206             :  *
    5207             :  * @note This method has only an effect on the in-memory feature object. If
    5208             :  * this object comes from a layer and the modifications must be serialized back
    5209             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5210             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5211             :  *
    5212             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    5213             :  * @param nYear (including century)
    5214             :  * @param nMonth (1-12)
    5215             :  * @param nDay (1-31)
    5216             :  * @param nHour (0-23)
    5217             :  * @param nMinute (0-59)
    5218             :  * @param fSecond (0-59, with millisecond accuracy)
    5219             :  * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
    5220             :  */
    5221             : 
    5222       10705 : void OGRFeature::SetField(int iField, int nYear, int nMonth, int nDay,
    5223             :                           int nHour, int nMinute, float fSecond, int nTZFlag)
    5224             : 
    5225             : {
    5226       10705 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    5227             : 
    5228       10705 :     if (poFDefn == nullptr)
    5229           0 :         return;
    5230             : 
    5231       10705 :     OGRFieldType eType = poFDefn->GetType();
    5232       10705 :     if (eType == OFTDate || eType == OFTTime || eType == OFTDateTime)
    5233             :     {
    5234       10697 :         if (static_cast<GInt16>(nYear) != nYear)
    5235             :         {
    5236           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    5237             :                      "Years < -32768 or > 32767 are not supported");
    5238           0 :             return;
    5239             :         }
    5240             : 
    5241       10697 :         pauFields[iField].Date.Year = static_cast<GInt16>(nYear);
    5242       10697 :         pauFields[iField].Date.Month = static_cast<GByte>(nMonth);
    5243       10697 :         pauFields[iField].Date.Day = static_cast<GByte>(nDay);
    5244       10697 :         pauFields[iField].Date.Hour = static_cast<GByte>(nHour);
    5245       10697 :         pauFields[iField].Date.Minute = static_cast<GByte>(nMinute);
    5246       10697 :         pauFields[iField].Date.Second = fSecond;
    5247       10697 :         pauFields[iField].Date.TZFlag = static_cast<GByte>(nTZFlag);
    5248             :     }
    5249           8 :     else if (eType == OFTString || eType == OFTStringList)
    5250             :     {
    5251             :         // "YYYY/MM/DD HH:MM:SS.sss+ZZ"
    5252           8 :         constexpr size_t MAX_SIZE = 26 + 1;
    5253           8 :         char szTempBuffer[MAX_SIZE] = {};
    5254           8 :         OGRFeatureFormatDateTimeBuffer(szTempBuffer, MAX_SIZE, nYear, nMonth,
    5255             :                                        nDay, nHour, nMinute, fSecond, nTZFlag);
    5256           8 :         SetField(iField, szTempBuffer);
    5257             :     }
    5258             : }
    5259             : 
    5260             : /************************************************************************/
    5261             : /*                       OGR_F_SetFieldDateTime()                       */
    5262             : /************************************************************************/
    5263             : 
    5264             : /**
    5265             :  * \brief Set field to datetime.
    5266             :  *
    5267             :  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
    5268             :  * fields.
    5269             :  *
    5270             :  * @note This method has only an effect on the in-memory feature object. If
    5271             :  * this object comes from a layer and the modifications must be serialized back
    5272             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5273             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5274             :  *
    5275             :  * @param hFeat handle to the feature that owned the field.
    5276             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    5277             :  * @param nYear (including century)
    5278             :  * @param nMonth (1-12)
    5279             :  * @param nDay (1-31)
    5280             :  * @param nHour (0-23)
    5281             :  * @param nMinute (0-59)
    5282             :  * @param nSecond (0-59)
    5283             :  * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
    5284             :  *
    5285             :  * @see Use OGR_F_SetFieldDateTimeEx() for second with millisecond accuracy.
    5286             :  */
    5287             : 
    5288           0 : void OGR_F_SetFieldDateTime(OGRFeatureH hFeat, int iField, int nYear,
    5289             :                             int nMonth, int nDay, int nHour, int nMinute,
    5290             :                             int nSecond, int nTZFlag)
    5291             : 
    5292             : {
    5293           0 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDateTime");
    5294             : 
    5295           0 :     OGRFeature::FromHandle(hFeat)->SetField(
    5296             :         iField, nYear, nMonth, nDay, nHour, nMinute,
    5297             :         static_cast<float>(nSecond), nTZFlag);
    5298             : }
    5299             : 
    5300             : /************************************************************************/
    5301             : /*                      OGR_F_SetFieldDateTimeEx()                      */
    5302             : /************************************************************************/
    5303             : 
    5304             : /**
    5305             :  * \brief Set field to datetime.
    5306             :  *
    5307             :  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
    5308             :  * fields.
    5309             :  *
    5310             :  * @note This method has only an effect on the in-memory feature object. If
    5311             :  * this object comes from a layer and the modifications must be serialized back
    5312             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5313             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5314             :  *
    5315             :  * @param hFeat handle to the feature that owned the field.
    5316             :  * @param iField the field to set, from 0 to GetFieldCount()-1.
    5317             :  * @param nYear (including century)
    5318             :  * @param nMonth (1-12)
    5319             :  * @param nDay (1-31)
    5320             :  * @param nHour (0-23)
    5321             :  * @param nMinute (0-59)
    5322             :  * @param fSecond (0-59, with millisecond accuracy)
    5323             :  * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
    5324             :  *
    5325             :  */
    5326             : 
    5327          45 : void OGR_F_SetFieldDateTimeEx(OGRFeatureH hFeat, int iField, int nYear,
    5328             :                               int nMonth, int nDay, int nHour, int nMinute,
    5329             :                               float fSecond, int nTZFlag)
    5330             : 
    5331             : {
    5332          45 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDateTimeEx");
    5333             : 
    5334          45 :     OGRFeature::FromHandle(hFeat)->SetField(iField, nYear, nMonth, nDay, nHour,
    5335             :                                             nMinute, fSecond, nTZFlag);
    5336             : }
    5337             : 
    5338             : /************************************************************************/
    5339             : /*                              SetField()                              */
    5340             : /************************************************************************/
    5341             : 
    5342             : /**
    5343             :  * \fn OGRFeature::SetField( const char* pszFName, const OGRField * puValue )
    5344             :  * \brief Set field.
    5345             :  *
    5346             :  * The passed value OGRField must be of exactly the same type as the
    5347             :  * target field, or an application crash may occur.  The passed value
    5348             :  * is copied, and will not be affected.  It remains the responsibility of
    5349             :  * the caller.
    5350             :  *
    5351             :  * @note This method has only an effect on the in-memory feature object. If
    5352             :  * this object comes from a layer and the modifications must be serialized back
    5353             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5354             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5355             :  *
    5356             :  * @param pszFName the name of the field to set.
    5357             :  * @param puValue the value to assign.
    5358             :  */
    5359             : 
    5360             : /**
    5361             :  * \brief Set field.
    5362             :  *
    5363             :  * The passed value OGRField must be of exactly the same type as the
    5364             :  * target field, or an application crash may occur.  The passed value
    5365             :  * is copied, and will not be affected.  It remains the responsibility of
    5366             :  * the caller.
    5367             :  *
    5368             :  * This method is the same as the C function OGR_F_SetFieldRaw().
    5369             :  *
    5370             :  * @note This method has only an effect on the in-memory feature object. If
    5371             :  * this object comes from a layer and the modifications must be serialized back
    5372             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5373             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5374             :  *
    5375             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    5376             :  * @param puValue the value to assign.
    5377             :  */
    5378             : 
    5379      390919 : void OGRFeature::SetField(int iField, const OGRField *puValue)
    5380             : 
    5381             : {
    5382      390919 :     SetFieldInternal(iField, puValue);
    5383      390919 : }
    5384             : 
    5385     4623370 : bool OGRFeature::SetFieldInternal(int iField, const OGRField *puValue)
    5386             : 
    5387             : {
    5388     4623370 :     const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
    5389     4623370 :     if (iField < 0 || poFDefn == nullptr)
    5390           0 :         return false;
    5391             : 
    5392     4623370 :     if (poFDefn->GetType() == OFTInteger)
    5393             :     {
    5394     1315440 :         pauFields[iField] = *puValue;
    5395             :     }
    5396     3307930 :     else if (poFDefn->GetType() == OFTInteger64)
    5397             :     {
    5398       25869 :         pauFields[iField] = *puValue;
    5399             :     }
    5400     3282060 :     else if (poFDefn->GetType() == OFTReal)
    5401             :     {
    5402       77715 :         pauFields[iField] = *puValue;
    5403             :     }
    5404     3204350 :     else if (poFDefn->GetType() == OFTString)
    5405             :     {
    5406     2910890 :         if (IsFieldSetAndNotNullUnsafe(iField))
    5407          28 :             CPLFree(pauFields[iField].String);
    5408             : 
    5409     2910890 :         if (puValue->String == nullptr)
    5410           0 :             pauFields[iField].String = nullptr;
    5411     2910890 :         else if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
    5412     1217950 :             pauFields[iField] = *puValue;
    5413             :         else
    5414             :         {
    5415     1692940 :             pauFields[iField].String = VSI_STRDUP_VERBOSE(puValue->String);
    5416     1692940 :             if (pauFields[iField].String == nullptr)
    5417             :             {
    5418           0 :                 OGR_RawField_SetUnset(&pauFields[iField]);
    5419           0 :                 return false;
    5420             :             }
    5421             :         }
    5422             :     }
    5423      542422 :     else if (poFDefn->GetType() == OFTDate || poFDefn->GetType() == OFTTime ||
    5424      248960 :              poFDefn->GetType() == OFTDateTime)
    5425             :     {
    5426      105660 :         memcpy(pauFields + iField, puValue, sizeof(OGRField));
    5427             :     }
    5428      187802 :     else if (poFDefn->GetType() == OFTIntegerList)
    5429             :     {
    5430       43845 :         const int nCount = puValue->IntegerList.nCount;
    5431             : 
    5432       43845 :         if (IsFieldSetAndNotNullUnsafe(iField))
    5433        3343 :             CPLFree(pauFields[iField].IntegerList.paList);
    5434             : 
    5435       43845 :         if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
    5436             :         {
    5437         350 :             pauFields[iField] = *puValue;
    5438             :         }
    5439             :         else
    5440             :         {
    5441       86990 :             pauFields[iField].IntegerList.paList =
    5442       43495 :                 static_cast<int *>(VSI_MALLOC_VERBOSE(sizeof(int) * nCount));
    5443       43495 :             if (pauFields[iField].IntegerList.paList == nullptr)
    5444             :             {
    5445           0 :                 OGR_RawField_SetUnset(&pauFields[iField]);
    5446           0 :                 return false;
    5447             :             }
    5448       43495 :             if (nCount > 0)
    5449             :             {
    5450       40487 :                 memcpy(pauFields[iField].IntegerList.paList,
    5451       40487 :                        puValue->IntegerList.paList, sizeof(int) * nCount);
    5452             :             }
    5453       43495 :             pauFields[iField].IntegerList.nCount = nCount;
    5454             :         }
    5455             :     }
    5456      143957 :     else if (poFDefn->GetType() == OFTInteger64List)
    5457             :     {
    5458       23326 :         const int nCount = puValue->Integer64List.nCount;
    5459             : 
    5460       23326 :         if (IsFieldSetAndNotNullUnsafe(iField))
    5461        1168 :             CPLFree(pauFields[iField].Integer64List.paList);
    5462             : 
    5463       23326 :         if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
    5464             :         {
    5465         111 :             pauFields[iField] = *puValue;
    5466             :         }
    5467             :         else
    5468             :         {
    5469       46430 :             pauFields[iField].Integer64List.paList = static_cast<GIntBig *>(
    5470       23215 :                 VSI_MALLOC_VERBOSE(sizeof(GIntBig) * nCount));
    5471       23215 :             if (pauFields[iField].Integer64List.paList == nullptr)
    5472             :             {
    5473           0 :                 OGR_RawField_SetUnset(&pauFields[iField]);
    5474           0 :                 return false;
    5475             :             }
    5476       23215 :             if (nCount > 0)
    5477             :             {
    5478       22252 :                 memcpy(pauFields[iField].Integer64List.paList,
    5479       22252 :                        puValue->Integer64List.paList, sizeof(GIntBig) * nCount);
    5480             :             }
    5481       23215 :             pauFields[iField].Integer64List.nCount = nCount;
    5482             :         }
    5483             :     }
    5484      120631 :     else if (poFDefn->GetType() == OFTRealList)
    5485             :     {
    5486       32047 :         const int nCount = puValue->RealList.nCount;
    5487             : 
    5488       32047 :         if (IsFieldSetAndNotNullUnsafe(iField))
    5489        2343 :             CPLFree(pauFields[iField].RealList.paList);
    5490             : 
    5491       32047 :         if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
    5492             :         {
    5493       10412 :             pauFields[iField] = *puValue;
    5494             :         }
    5495             :         else
    5496             :         {
    5497       43270 :             pauFields[iField].RealList.paList = static_cast<double *>(
    5498       21635 :                 VSI_MALLOC_VERBOSE(sizeof(double) * nCount));
    5499       21635 :             if (pauFields[iField].RealList.paList == nullptr)
    5500             :             {
    5501           0 :                 OGR_RawField_SetUnset(&pauFields[iField]);
    5502           0 :                 return false;
    5503             :             }
    5504       21635 :             if (nCount > 0)
    5505             :             {
    5506       20012 :                 memcpy(pauFields[iField].RealList.paList,
    5507       20012 :                        puValue->RealList.paList, sizeof(double) * nCount);
    5508             :             }
    5509       21635 :             pauFields[iField].RealList.nCount = nCount;
    5510             :         }
    5511             :     }
    5512       88584 :     else if (poFDefn->GetType() == OFTStringList)
    5513             :     {
    5514       29676 :         if (IsFieldSetAndNotNullUnsafe(iField))
    5515        5627 :             CSLDestroy(pauFields[iField].StringList.paList);
    5516             : 
    5517       29676 :         if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
    5518             :         {
    5519         272 :             pauFields[iField] = *puValue;
    5520             :         }
    5521             :         else
    5522             :         {
    5523       29404 :             char **papszNewList = nullptr;
    5524       29404 :             for (char **papszIter = puValue->StringList.paList;
    5525       84316 :                  papszIter != nullptr && *papszIter != nullptr; ++papszIter)
    5526             :             {
    5527             :                 char **papszNewList2 =
    5528       54912 :                     CSLAddStringMayFail(papszNewList, *papszIter);
    5529       54912 :                 if (papszNewList2 == nullptr)
    5530             :                 {
    5531           0 :                     CSLDestroy(papszNewList);
    5532           0 :                     OGR_RawField_SetUnset(&pauFields[iField]);
    5533           0 :                     return false;
    5534             :                 }
    5535       54912 :                 papszNewList = papszNewList2;
    5536             :             }
    5537       29404 :             pauFields[iField].StringList.paList = papszNewList;
    5538       29404 :             pauFields[iField].StringList.nCount = puValue->StringList.nCount;
    5539       29404 :             CPLAssert(CSLCount(puValue->StringList.paList) ==
    5540             :                       puValue->StringList.nCount);
    5541             :         }
    5542             :     }
    5543       58908 :     else if (poFDefn->GetType() == OFTBinary)
    5544             :     {
    5545       58908 :         if (IsFieldSetAndNotNullUnsafe(iField))
    5546         103 :             CPLFree(pauFields[iField].Binary.paData);
    5547             : 
    5548       58908 :         if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
    5549             :         {
    5550         105 :             pauFields[iField] = *puValue;
    5551             :         }
    5552             :         else
    5553             :         {
    5554      117606 :             pauFields[iField].Binary.paData = static_cast<GByte *>(
    5555       58803 :                 VSI_MALLOC_VERBOSE(puValue->Binary.nCount));
    5556       58803 :             if (pauFields[iField].Binary.paData == nullptr)
    5557             :             {
    5558           0 :                 OGR_RawField_SetUnset(&pauFields[iField]);
    5559           0 :                 return false;
    5560             :             }
    5561       58803 :             if (puValue->Binary.nCount > 0)
    5562             :             {
    5563       58760 :                 memcpy(pauFields[iField].Binary.paData, puValue->Binary.paData,
    5564       58760 :                        puValue->Binary.nCount);
    5565             :             }
    5566       58803 :             pauFields[iField].Binary.nCount = puValue->Binary.nCount;
    5567             :         }
    5568             :     }
    5569             :     else
    5570             :     {
    5571             :         // Do nothing for other field types.
    5572             :     }
    5573     4623370 :     return true;
    5574             : }
    5575             : 
    5576             : /************************************************************************/
    5577             : /*                         OGR_F_SetFieldRaw()                          */
    5578             : /************************************************************************/
    5579             : 
    5580             : /**
    5581             :  * \brief Set field.
    5582             :  *
    5583             :  * The passed value OGRField must be of exactly the same type as the
    5584             :  * target field, or an application crash may occur.  The passed value
    5585             :  * is copied, and will not be affected.  It remains the responsibility of
    5586             :  * the caller.
    5587             :  *
    5588             :  * This function is the same as the C++ method OGRFeature::SetField().
    5589             :  *
    5590             :  * @note This method has only an effect on the in-memory feature object. If
    5591             :  * this object comes from a layer and the modifications must be serialized back
    5592             :  * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
    5593             :  * a new feature, OGR_L_CreateFeature() must be used afterwards.
    5594             :  *
    5595             :  * @param hFeat handle to the feature that owned the field.
    5596             :  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
    5597             :  * @param psValue handle on the value to assign.
    5598             :  */
    5599             : 
    5600           0 : void OGR_F_SetFieldRaw(OGRFeatureH hFeat, int iField, const OGRField *psValue)
    5601             : 
    5602             : {
    5603           0 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldRaw");
    5604             : 
    5605           0 :     OGRFeature::FromHandle(hFeat)->SetField(iField, psValue);
    5606             : }
    5607             : 
    5608             : /************************************************************************/
    5609             : /*                            DumpReadable()                            */
    5610             : /************************************************************************/
    5611             : 
    5612             : /**
    5613             :  * \brief Dump this feature in a human readable form.
    5614             :  *
    5615             :  * This dumps the attributes, and geometry; however, it doesn't definition
    5616             :  * information (other than field types and names), nor does it report the
    5617             :  * geometry spatial reference system.
    5618             :  *
    5619             :  * A few options can be defined to change the default dump :
    5620             :  * <ul>
    5621             :  * <li>DISPLAY_FIELDS=NO : to hide the dump of the attributes</li>
    5622             :  * <li>DISPLAY_STYLE=NO : to hide the dump of the style string</li>
    5623             :  * <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
    5624             :  * <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
    5625             :  * </ul>
    5626             :  *
    5627             :  * This method is the same as the C function OGR_F_DumpReadable().
    5628             :  *
    5629             :  * @param fpOut the stream to write to, such as stdout.  If NULL stdout will
    5630             :  * be used.
    5631             :  * @param papszOptions NULL terminated list of options (may be NULL)
    5632             :  */
    5633             : 
    5634         121 : void OGRFeature::DumpReadable(FILE *fpOut, CSLConstList papszOptions) const
    5635             : 
    5636             : {
    5637         121 :     if (fpOut == nullptr)
    5638         121 :         fpOut = stdout;
    5639             : 
    5640         242 :     const auto osStr = DumpReadableAsString(papszOptions);
    5641         121 :     fprintf(fpOut, "%s", osStr.c_str());
    5642         121 : }
    5643             : 
    5644             : /************************************************************************/
    5645             : /*                        DumpReadableAsString()                        */
    5646             : /************************************************************************/
    5647             : 
    5648             : /**
    5649             :  * \brief Dump this feature in a human readable form.
    5650             :  *
    5651             :  * This dumps the attributes, and geometry; however, it doesn't definition
    5652             :  * information (other than field types and names), nor does it report the
    5653             :  * geometry spatial reference system.
    5654             :  *
    5655             :  * A few options can be defined to change the default dump :
    5656             :  * <ul>
    5657             :  * <li>DISPLAY_FIELDS=NO : to hide the dump of the attributes</li>
    5658             :  * <li>DISPLAY_STYLE=NO : to hide the dump of the style string</li>
    5659             :  * <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
    5660             :  * <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
    5661             :  * </ul>
    5662             :  *
    5663             :  * @param papszOptions NULL terminated list of options (may be NULL)
    5664             :  * @return a string with the feature representation.
    5665             :  * @since GDAL 3.7
    5666             :  */
    5667             : 
    5668         827 : std::string OGRFeature::DumpReadableAsString(CSLConstList papszOptions) const
    5669             : {
    5670         827 :     std::string osRet;
    5671             : 
    5672        1654 :     osRet += CPLOPrintf("OGRFeature(%s):" CPL_FRMT_GIB "\n", poDefn->GetName(),
    5673         827 :                         GetFID());
    5674             : 
    5675             :     const char *pszDisplayFields =
    5676         827 :         CSLFetchNameValue(papszOptions, "DISPLAY_FIELDS");
    5677         827 :     if (pszDisplayFields == nullptr || CPLTestBool(pszDisplayFields))
    5678             :     {
    5679         816 :         const int nFieldCount = GetFieldCount();
    5680        8168 :         for (int iField = 0; iField < nFieldCount; iField++)
    5681             :         {
    5682        7352 :             if (!IsFieldSet(iField))
    5683        2560 :                 continue;
    5684        4792 :             const OGRFieldDefn *poFDefn = poDefn->GetFieldDefnUnsafe(iField);
    5685             : 
    5686             :             const char *pszType =
    5687        4792 :                 (poFDefn->GetSubType() != OFSTNone)
    5688        4792 :                     ? CPLSPrintf(
    5689             :                           "%s(%s)",
    5690             :                           poFDefn->GetFieldTypeName(poFDefn->GetType()),
    5691             :                           poFDefn->GetFieldSubTypeName(poFDefn->GetSubType()))
    5692        4354 :                     : poFDefn->GetFieldTypeName(poFDefn->GetType());
    5693             : 
    5694        4792 :             osRet += CPLOPrintf("  %s (%s) = ", poFDefn->GetNameRef(), pszType);
    5695             : 
    5696        4792 :             if (IsFieldNull(iField))
    5697          45 :                 osRet += "(null)\n";
    5698             :             else
    5699        4747 :                 osRet += CPLOPrintf("%s\n", GetFieldAsString(iField));
    5700             :         }
    5701             :     }
    5702             : 
    5703         827 :     if (GetStyleString() != nullptr)
    5704             :     {
    5705             :         const char *pszDisplayStyle =
    5706           4 :             CSLFetchNameValue(papszOptions, "DISPLAY_STYLE");
    5707           4 :         if (pszDisplayStyle == nullptr || CPLTestBool(pszDisplayStyle))
    5708             :         {
    5709           4 :             osRet += CPLOPrintf("  Style = %s\n", GetStyleString());
    5710             :         }
    5711             :     }
    5712             : 
    5713         827 :     const int nGeomFieldCount = GetGeomFieldCount();
    5714         827 :     if (nGeomFieldCount > 0)
    5715             :     {
    5716             :         const char *pszDisplayGeometry =
    5717         311 :             CSLFetchNameValue(papszOptions, "DISPLAY_GEOMETRY");
    5718         311 :         if (!(pszDisplayGeometry != nullptr && EQUAL(pszDisplayGeometry, "NO")))
    5719             :         {
    5720         606 :             for (int iField = 0; iField < nGeomFieldCount; iField++)
    5721             :             {
    5722             :                 const OGRGeomFieldDefn *poFDefn =
    5723         306 :                     poDefn->GetGeomFieldDefn(iField);
    5724             : 
    5725         306 :                 if (papoGeometries[iField] != nullptr)
    5726             :                 {
    5727         303 :                     CPLStringList aosGeomOptions(papszOptions);
    5728             : 
    5729         303 :                     const auto &oCoordPrec = poFDefn->GetCoordinatePrecision();
    5730             : 
    5731         303 :                     if (oCoordPrec.dfXYResolution !=
    5732             :                         OGRGeomCoordinatePrecision::UNKNOWN)
    5733             :                     {
    5734             :                         aosGeomOptions.SetNameValue(
    5735             :                             "XY_COORD_PRECISION",
    5736             :                             CPLSPrintf("%d",
    5737             :                                        OGRGeomCoordinatePrecision::
    5738             :                                            ResolutionToPrecision(
    5739           1 :                                                oCoordPrec.dfXYResolution)));
    5740             :                     }
    5741         303 :                     if (oCoordPrec.dfZResolution !=
    5742             :                         OGRGeomCoordinatePrecision::UNKNOWN)
    5743             :                     {
    5744             :                         aosGeomOptions.SetNameValue(
    5745             :                             "Z_COORD_PRECISION",
    5746             :                             CPLSPrintf("%d",
    5747             :                                        OGRGeomCoordinatePrecision::
    5748             :                                            ResolutionToPrecision(
    5749           1 :                                                oCoordPrec.dfZResolution)));
    5750             :                     }
    5751             : 
    5752         303 :                     osRet += "  ";
    5753         355 :                     if (strlen(poFDefn->GetNameRef()) > 0 &&
    5754          52 :                         GetGeomFieldCount() > 1)
    5755          12 :                         osRet += CPLOPrintf("%s = ", poFDefn->GetNameRef());
    5756         606 :                     osRet += papoGeometries[iField]->dumpReadable(
    5757         606 :                         nullptr, aosGeomOptions.List());
    5758             :                 }
    5759             :             }
    5760             :         }
    5761             :     }
    5762             : 
    5763         827 :     osRet += "\n";
    5764         827 :     return osRet;
    5765             : }
    5766             : 
    5767             : /************************************************************************/
    5768             : /*                         OGR_F_DumpReadable()                         */
    5769             : /************************************************************************/
    5770             : 
    5771             : /**
    5772             :  * \brief Dump this feature in a human readable form.
    5773             :  *
    5774             :  * This dumps the attributes, and geometry; however, it doesn't definition
    5775             :  * information (other than field types and names), nor does it report the
    5776             :  * geometry spatial reference system.
    5777             :  *
    5778             :  * This function is the same as the C++ method OGRFeature::DumpReadable().
    5779             :  *
    5780             :  * @param hFeat handle to the feature to dump.
    5781             :  * @param fpOut the stream to write to, such as strout.
    5782             :  */
    5783             : 
    5784          31 : void OGR_F_DumpReadable(OGRFeatureH hFeat, FILE *fpOut)
    5785             : 
    5786             : {
    5787          31 :     VALIDATE_POINTER0(hFeat, "OGR_F_DumpReadable");
    5788             : 
    5789          31 :     OGRFeature::FromHandle(hFeat)->DumpReadable(fpOut);
    5790             : }
    5791             : 
    5792             : /************************************************************************/
    5793             : /*                     OGR_F_DumpReadableAsString()                     */
    5794             : /************************************************************************/
    5795             : 
    5796             : /**
    5797             :  * \brief Dump this feature in a human readable form.
    5798             :  *
    5799             :  * This dumps the attributes, and geometry; however, it doesn't include
    5800             :  * definition information (other than field types and names), nor does
    5801             :  * it report the geometry spatial reference system.
    5802             :  *
    5803             :  * A few options can be defined to change the default dump :
    5804             :  * <ul>
    5805             :  * <li>DISPLAY_FIELDS=NO : to hide the dump of the attributes</li>
    5806             :  * <li>DISPLAY_STYLE=NO : to hide the dump of the style string</li>
    5807             :  * <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
    5808             :  * <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
    5809             :  * </ul>
    5810             :  *
    5811             :  * @param hFeat handle to the feature to dump.
    5812             :  * @param papszOptions NULL terminated list of options (may be NULL)
    5813             :  * @return a string with the feature representation (to be freed with CPLFree())
    5814             :  * @since GDAL 3.8
    5815             :  */
    5816             : 
    5817          96 : char *OGR_F_DumpReadableAsString(OGRFeatureH hFeat, CSLConstList papszOptions)
    5818             : {
    5819          96 :     VALIDATE_POINTER1(hFeat, "OGR_F_DumpReadableAsString", nullptr);
    5820             : 
    5821          96 :     return CPLStrdup(OGRFeature::FromHandle(hFeat)
    5822         192 :                          ->DumpReadableAsString(papszOptions)
    5823          96 :                          .c_str());
    5824             : }
    5825             : 
    5826             : /************************************************************************/
    5827             : /*                               GetFID()                               */
    5828             : /************************************************************************/
    5829             : 
    5830             : /**
    5831             :  * \fn GIntBig OGRFeature::GetFID() const;
    5832             :  *
    5833             :  * \brief Get feature identifier.
    5834             :  *
    5835             :  * This method is the same as the C function OGR_F_GetFID().
    5836             :  *
    5837             :  * @return feature id or OGRNullFID if none has been assigned.
    5838             :  */
    5839             : 
    5840             : /************************************************************************/
    5841             : /*                            OGR_F_GetFID()                            */
    5842             : /************************************************************************/
    5843             : 
    5844             : /**
    5845             :  * \brief Get feature identifier.
    5846             :  *
    5847             :  * This function is the same as the C++ method OGRFeature::GetFID().
    5848             :  *
    5849             :  * @param hFeat handle to the feature from which to get the feature
    5850             :  * identifier.
    5851             :  * @return feature id or OGRNullFID if none has been assigned.
    5852             :  */
    5853             : 
    5854        5475 : GIntBig OGR_F_GetFID(OGRFeatureH hFeat)
    5855             : 
    5856             : {
    5857        5475 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetFID", 0);
    5858             : 
    5859        5475 :     return OGRFeature::FromHandle(hFeat)->GetFID();
    5860             : }
    5861             : 
    5862             : /************************************************************************/
    5863             : /*                               SetFID()                               */
    5864             : /************************************************************************/
    5865             : 
    5866             : /**
    5867             :  * \brief Set the feature identifier.
    5868             :  *
    5869             :  * For specific types of features this operation may fail on illegal
    5870             :  * features ids.  Generally it always succeeds.  Feature ids should be
    5871             :  * greater than or equal to zero, with the exception of OGRNullFID (-1)
    5872             :  * indicating that the feature id is unknown.
    5873             :  *
    5874             :  * This method is the same as the C function OGR_F_SetFID().
    5875             :  *
    5876             :  * @param nFIDIn the new feature identifier value to assign.
    5877             :  *
    5878             :  * @return On success OGRERR_NONE, or on failure some other value.
    5879             :  */
    5880             : 
    5881     3041630 : OGRErr OGRFeature::SetFID(GIntBig nFIDIn)
    5882             : 
    5883             : {
    5884     3041630 :     nFID = nFIDIn;
    5885             : 
    5886     3041630 :     return OGRERR_NONE;
    5887             : }
    5888             : 
    5889             : /************************************************************************/
    5890             : /*                            OGR_F_SetFID()                            */
    5891             : /************************************************************************/
    5892             : 
    5893             : /**
    5894             :  * \brief Set the feature identifier.
    5895             :  *
    5896             :  * For specific types of features this operation may fail on illegal
    5897             :  * features ids.  Generally it always succeeds.  Feature ids should be
    5898             :  * greater than or equal to zero, with the exception of OGRNullFID (-1)
    5899             :  * indicating that the feature id is unknown.
    5900             :  *
    5901             :  * This function is the same as the C++ method OGRFeature::SetFID().
    5902             :  *
    5903             :  * @param hFeat handle to the feature to set the feature id to.
    5904             :  * @param nFID the new feature identifier value to assign.
    5905             :  *
    5906             :  * @return On success OGRERR_NONE, or on failure some other value.
    5907             :  */
    5908             : 
    5909      170868 : OGRErr OGR_F_SetFID(OGRFeatureH hFeat, GIntBig nFID)
    5910             : 
    5911             : {
    5912      170868 :     VALIDATE_POINTER1(hFeat, "OGR_F_SetFID", OGRERR_FAILURE);
    5913             : 
    5914      170868 :     return OGRFeature::FromHandle(hFeat)->SetFID(nFID);
    5915             : }
    5916             : 
    5917             : /************************************************************************/
    5918             : /*                               Equal()                                */
    5919             : /************************************************************************/
    5920             : 
    5921             : /**
    5922             :  * \brief Test if two features are the same.
    5923             :  *
    5924             :  * Two features are considered equal if the share them (pointer equality)
    5925             :  * same OGRFeatureDefn, have the same field values, and the same geometry
    5926             :  * (as tested by OGRGeometry::Equal()) as well as the same feature id.
    5927             :  *
    5928             :  * This method is the same as the C function OGR_F_Equal().
    5929             :  *
    5930             :  * @param poFeature the other feature to test this one against.
    5931             :  *
    5932             :  * @return TRUE if they are equal, otherwise FALSE.
    5933             :  */
    5934             : 
    5935       56424 : OGRBoolean OGRFeature::Equal(const OGRFeature *poFeature) const
    5936             : 
    5937             : {
    5938       56424 :     if (poFeature == this)
    5939           1 :         return TRUE;
    5940             : 
    5941       56423 :     if (GetFID() != poFeature->GetFID())
    5942       53304 :         return FALSE;
    5943             : 
    5944        3119 :     if (GetDefnRef() != poFeature->GetDefnRef())
    5945          11 :         return FALSE;
    5946             : 
    5947        3108 :     const int nFields = GetDefnRef()->GetFieldCountUnsafe();
    5948       27306 :     for (int i = 0; i < nFields; i++)
    5949             :     {
    5950       24313 :         if (IsFieldSet(i) != poFeature->IsFieldSet(i))
    5951           2 :             return FALSE;
    5952       24311 :         if (IsFieldNull(i) != poFeature->IsFieldNull(i))
    5953           0 :             return FALSE;
    5954       24311 :         if (!IsFieldSetAndNotNullUnsafe(i))
    5955        3552 :             continue;
    5956             : 
    5957       20759 :         switch (GetDefnRef()->GetFieldDefnUnsafe(i)->GetType())
    5958             :         {
    5959        5672 :             case OFTInteger:
    5960        5672 :                 if (GetFieldAsInteger(i) != poFeature->GetFieldAsInteger(i))
    5961          18 :                     return FALSE;
    5962        5654 :                 break;
    5963             : 
    5964         669 :             case OFTInteger64:
    5965         669 :                 if (GetFieldAsInteger64(i) != poFeature->GetFieldAsInteger64(i))
    5966           4 :                     return FALSE;
    5967         665 :                 break;
    5968             : 
    5969        4250 :             case OFTReal:
    5970             :             {
    5971        4250 :                 const double dfVal1 = GetFieldAsDouble(i);
    5972        4250 :                 const double dfVal2 = poFeature->GetFieldAsDouble(i);
    5973        4250 :                 if (std::isnan(dfVal1))
    5974             :                 {
    5975           7 :                     if (!std::isnan(dfVal2))
    5976           1 :                         return FALSE;
    5977             :                 }
    5978        4243 :                 else if (std::isnan(dfVal2))
    5979             :                 {
    5980           1 :                     return FALSE;
    5981             :                 }
    5982        4242 :                 else if (dfVal1 != dfVal2)
    5983             :                 {
    5984          16 :                     return FALSE;
    5985             :                 }
    5986        4232 :                 break;
    5987             :             }
    5988             : 
    5989        5571 :             case OFTString:
    5990        5571 :                 if (strcmp(GetFieldAsString(i),
    5991        5571 :                            poFeature->GetFieldAsString(i)) != 0)
    5992          15 :                     return FALSE;
    5993        5556 :                 break;
    5994             : 
    5995         447 :             case OFTIntegerList:
    5996             :             {
    5997         447 :                 int nCount1 = 0;
    5998         447 :                 int nCount2 = 0;
    5999         447 :                 const int *pnList1 = GetFieldAsIntegerList(i, &nCount1);
    6000             :                 const int *pnList2 =
    6001         447 :                     poFeature->GetFieldAsIntegerList(i, &nCount2);
    6002         447 :                 if (nCount1 != nCount2)
    6003           4 :                     return FALSE;
    6004        1247 :                 for (int j = 0; j < nCount1; j++)
    6005             :                 {
    6006         804 :                     if (pnList1[j] != pnList2[j])
    6007           2 :                         return FALSE;
    6008             :                 }
    6009         443 :                 break;
    6010             :             }
    6011             : 
    6012         168 :             case OFTInteger64List:
    6013             :             {
    6014         168 :                 int nCount1 = 0;
    6015         168 :                 int nCount2 = 0;
    6016         168 :                 const GIntBig *pnList1 = GetFieldAsInteger64List(i, &nCount1);
    6017             :                 const GIntBig *pnList2 =
    6018         168 :                     poFeature->GetFieldAsInteger64List(i, &nCount2);
    6019         168 :                 if (nCount1 != nCount2)
    6020           0 :                     return FALSE;
    6021         497 :                 for (int j = 0; j < nCount1; j++)
    6022             :                 {
    6023         329 :                     if (pnList1[j] != pnList2[j])
    6024           0 :                         return FALSE;
    6025             :                 }
    6026         168 :                 break;
    6027             :             }
    6028             : 
    6029         326 :             case OFTRealList:
    6030             :             {
    6031         326 :                 int nCount1 = 0;
    6032         326 :                 int nCount2 = 0;
    6033         326 :                 const double *padfList1 = GetFieldAsDoubleList(i, &nCount1);
    6034             :                 const double *padfList2 =
    6035         326 :                     poFeature->GetFieldAsDoubleList(i, &nCount2);
    6036         326 :                 if (nCount1 != nCount2)
    6037           6 :                     return FALSE;
    6038         928 :                 for (int j = 0; j < nCount1; j++)
    6039             :                 {
    6040         608 :                     const double dfVal1 = padfList1[j];
    6041         608 :                     const double dfVal2 = padfList2[j];
    6042         608 :                     if (std::isnan(dfVal1))
    6043             :                     {
    6044         126 :                         if (!std::isnan(dfVal2))
    6045           1 :                             return FALSE;
    6046             :                     }
    6047         482 :                     else if (std::isnan(dfVal2))
    6048             :                     {
    6049           1 :                         return FALSE;
    6050             :                     }
    6051         481 :                     else if (dfVal1 != dfVal2)
    6052             :                     {
    6053           2 :                         return FALSE;
    6054             :                     }
    6055             :                 }
    6056         320 :                 break;
    6057             :             }
    6058             : 
    6059         170 :             case OFTStringList:
    6060             :             {
    6061         170 :                 int nCount1 = 0;
    6062         170 :                 int nCount2 = 0;
    6063         170 :                 char **papszList1 = GetFieldAsStringList(i);
    6064         170 :                 char **papszList2 = poFeature->GetFieldAsStringList(i);
    6065         170 :                 nCount1 = CSLCount(papszList1);
    6066         170 :                 nCount2 = CSLCount(papszList2);
    6067         170 :                 if (nCount1 != nCount2)
    6068           2 :                     return FALSE;
    6069         430 :                 for (int j = 0; j < nCount1; j++)
    6070             :                 {
    6071         264 :                     if (strcmp(papszList1[j], papszList2[j]) != 0)
    6072           2 :                         return FALSE;
    6073             :                 }
    6074         166 :                 break;
    6075             :             }
    6076             : 
    6077        1472 :             case OFTTime:
    6078             :             case OFTDate:
    6079             :             case OFTDateTime:
    6080             :             {
    6081        1472 :                 int nYear1 = 0;
    6082        1472 :                 int nMonth1 = 0;
    6083        1472 :                 int nDay1 = 0;
    6084        1472 :                 int nHour1 = 0;
    6085        1472 :                 int nMinute1 = 0;
    6086        1472 :                 int nTZFlag1 = 0;
    6087        1472 :                 int nYear2 = 0;
    6088        1472 :                 int nMonth2 = 0;
    6089        1472 :                 int nDay2 = 0;
    6090        1472 :                 int nHour2 = 0;
    6091        1472 :                 int nMinute2 = 0;
    6092        1472 :                 int nTZFlag2 = 0;
    6093        1472 :                 float fSecond1 = 0.0f;
    6094        1472 :                 float fSecond2 = 0.0f;
    6095        1472 :                 GetFieldAsDateTime(i, &nYear1, &nMonth1, &nDay1, &nHour1,
    6096             :                                    &nMinute1, &fSecond1, &nTZFlag1);
    6097        1472 :                 poFeature->GetFieldAsDateTime(i, &nYear2, &nMonth2, &nDay2,
    6098             :                                               &nHour2, &nMinute2, &fSecond2,
    6099             :                                               &nTZFlag2);
    6100             : 
    6101        1472 :                 if (!(nYear1 == nYear2 && nMonth1 == nMonth2 &&
    6102        1460 :                       nDay1 == nDay2 && nHour1 == nHour2 &&
    6103        1448 :                       nMinute1 == nMinute2 && fSecond1 == fSecond2 &&
    6104        1436 :                       nTZFlag1 == nTZFlag2))
    6105          42 :                     return FALSE;
    6106        1430 :                 break;
    6107             :             }
    6108             : 
    6109        2014 :             case OFTBinary:
    6110             :             {
    6111        2014 :                 int nCount1 = 0;
    6112        2014 :                 int nCount2 = 0;
    6113        2014 :                 GByte *pabyData1 = GetFieldAsBinary(i, &nCount1);
    6114        2014 :                 GByte *pabyData2 = poFeature->GetFieldAsBinary(i, &nCount2);
    6115        2014 :                 if (nCount1 != nCount2)
    6116           2 :                     return FALSE;
    6117        2012 :                 if (memcmp(pabyData1, pabyData2, nCount1) != 0)
    6118           0 :                     return FALSE;
    6119        2012 :                 break;
    6120             :             }
    6121             : 
    6122           0 :             default:
    6123           0 :                 if (strcmp(GetFieldAsString(i),
    6124           0 :                            poFeature->GetFieldAsString(i)) != 0)
    6125           0 :                     return FALSE;
    6126           0 :                 break;
    6127             :         }
    6128             :     }
    6129             : 
    6130        2993 :     const int nGeomFieldCount = GetGeomFieldCount();
    6131        5682 :     for (int i = 0; i < nGeomFieldCount; i++)
    6132             :     {
    6133        2801 :         const OGRGeometry *poThisGeom = GetGeomFieldRef(i);
    6134        2801 :         const OGRGeometry *poOtherGeom = poFeature->GetGeomFieldRef(i);
    6135             : 
    6136        2801 :         if (poThisGeom == nullptr && poOtherGeom != nullptr)
    6137           3 :             return FALSE;
    6138             : 
    6139        2798 :         if (poThisGeom != nullptr && poOtherGeom == nullptr)
    6140           4 :             return FALSE;
    6141             : 
    6142        5408 :         if (poThisGeom != nullptr && poOtherGeom != nullptr &&
    6143        2614 :             (!poThisGeom->Equals(poOtherGeom)))
    6144         105 :             return FALSE;
    6145             :     }
    6146             : 
    6147        2881 :     return TRUE;
    6148             : }
    6149             : 
    6150             : /************************************************************************/
    6151             : /*                            OGR_F_Equal()                             */
    6152             : /************************************************************************/
    6153             : 
    6154             : /**
    6155             :  * \brief Test if two features are the same.
    6156             :  *
    6157             :  * Two features are considered equal if the share them (handle equality)
    6158             :  * same OGRFeatureDefn, have the same field values, and the same geometry
    6159             :  * (as tested by OGR_G_Equal()) as well as the same feature id.
    6160             :  *
    6161             :  * This function is the same as the C++ method OGRFeature::Equal().
    6162             :  *
    6163             :  * @param hFeat handle to one of the feature.
    6164             :  * @param hOtherFeat handle to the other feature to test this one against.
    6165             :  *
    6166             :  * @return TRUE if they are equal, otherwise FALSE.
    6167             :  */
    6168             : 
    6169         109 : int OGR_F_Equal(OGRFeatureH hFeat, OGRFeatureH hOtherFeat)
    6170             : 
    6171             : {
    6172         109 :     VALIDATE_POINTER1(hFeat, "OGR_F_Equal", 0);
    6173         109 :     VALIDATE_POINTER1(hOtherFeat, "OGR_F_Equal", 0);
    6174             : 
    6175         218 :     return OGRFeature::FromHandle(hFeat)->Equal(
    6176         109 :         OGRFeature::FromHandle(hOtherFeat));
    6177             : }
    6178             : 
    6179             : /************************************************************************/
    6180             : /*                              SetFrom()                               */
    6181             : /************************************************************************/
    6182             : 
    6183             : /**
    6184             :  * \brief Set one feature from another.
    6185             :  *
    6186             :  * Overwrite the contents of this feature from the geometry and attributes
    6187             :  * of another.  The poSrcFeature does not need to have the same
    6188             :  * OGRFeatureDefn.  Field values are copied by corresponding field names.
    6189             :  * Field types do not have to exactly match.  SetField() method conversion
    6190             :  * rules will be applied as needed.
    6191             :  *
    6192             :  * This method is the same as the C function OGR_F_SetFrom().
    6193             :  *
    6194             :  * @param poSrcFeature the feature from which geometry, and field values will
    6195             :  * be copied.
    6196             :  *
    6197             :  * @param bForgiving TRUE if the operation should continue despite lacking
    6198             :  * output fields matching some of the source fields.
    6199             :  *
    6200             :  * @return OGRERR_NONE if the operation succeeds, even if some values are
    6201             :  * not transferred, otherwise an error code.
    6202             :  */
    6203             : 
    6204        4963 : OGRErr OGRFeature::SetFrom(const OGRFeature *poSrcFeature, int bForgiving)
    6205             : 
    6206             : {
    6207        4963 :     const auto &oMap = poDefn->ComputeMapForSetFrom(poSrcFeature->GetDefnRef(),
    6208        9926 :                                                     CPL_TO_BOOL(bForgiving));
    6209        4963 :     if (oMap.empty())
    6210             :     {
    6211         262 :         if (poSrcFeature->GetFieldCount())
    6212           0 :             return OGRERR_FAILURE;
    6213         262 :         int dummy = 0;
    6214         262 :         return SetFrom(poSrcFeature, &dummy, bForgiving);
    6215             :     }
    6216        4701 :     return SetFrom(poSrcFeature, oMap.data(), bForgiving);
    6217             : }
    6218             : 
    6219             : /************************************************************************/
    6220             : /*                           OGR_F_SetFrom()                            */
    6221             : /************************************************************************/
    6222             : 
    6223             : /**
    6224             :  * \brief Set one feature from another.
    6225             :  *
    6226             :  * Overwrite the contents of this feature from the geometry and attributes
    6227             :  * of another.  The hOtherFeature does not need to have the same
    6228             :  * OGRFeatureDefn.  Field values are copied by corresponding field names.
    6229             :  * Field types do not have to exactly match.  OGR_F_SetField*() function
    6230             :  * conversion rules will be applied as needed.
    6231             :  *
    6232             :  * This function is the same as the C++ method OGRFeature::SetFrom().
    6233             :  *
    6234             :  * @param hFeat handle to the feature to set to.
    6235             :  * @param hOtherFeat handle to the feature from which geometry,
    6236             :  * and field values will be copied.
    6237             :  *
    6238             :  * @param bForgiving TRUE if the operation should continue despite lacking
    6239             :  * output fields matching some of the source fields.
    6240             :  *
    6241             :  * @return OGRERR_NONE if the operation succeeds, even if some values are
    6242             :  * not transferred, otherwise an error code.
    6243             :  */
    6244             : 
    6245        1812 : OGRErr OGR_F_SetFrom(OGRFeatureH hFeat, OGRFeatureH hOtherFeat, int bForgiving)
    6246             : 
    6247             : {
    6248        1812 :     VALIDATE_POINTER1(hFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
    6249        1812 :     VALIDATE_POINTER1(hOtherFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
    6250             : 
    6251        3624 :     return OGRFeature::FromHandle(hFeat)->SetFrom(
    6252        3624 :         OGRFeature::FromHandle(hOtherFeat), bForgiving);
    6253             : }
    6254             : 
    6255             : /************************************************************************/
    6256             : /*                              SetFrom()                               */
    6257             : /************************************************************************/
    6258             : 
    6259             : /**
    6260             :  * \brief Set one feature from another.
    6261             :  *
    6262             :  * Overwrite the contents of this feature from the geometry and attributes
    6263             :  * of another.  The poSrcFeature does not need to have the same
    6264             :  * OGRFeatureDefn.  Field values are copied according to the provided indices
    6265             :  * map. Field types do not have to exactly match.  SetField() method
    6266             :  * conversion rules will be applied as needed. This is more efficient than
    6267             :  * OGR_F_SetFrom() in that this doesn't lookup the fields by their names.
    6268             :  * Particularly useful when the field names don't match.
    6269             :  *
    6270             :  * This method is the same as the C function OGR_F_SetFromWithMap().
    6271             :  *
    6272             :  * @param poSrcFeature the feature from which geometry, and field values will
    6273             :  * be copied.
    6274             :  *
    6275             :  * @param panMap Array of the indices of the feature's fields
    6276             :  * stored at the corresponding index of the source feature's fields. A value of
    6277             :  * -1 should be used to ignore the source's field. The array should not be NULL
    6278             :  * and be as long as the number of fields in the source feature.
    6279             :  *
    6280             :  * @param bForgiving TRUE if the operation should continue despite lacking
    6281             :  * output fields matching some of the source fields.
    6282             :  *
    6283             :  * @param bUseISO8601ForDateTimeAsString true if datetime fields
    6284             :  * converted to string should use ISO8601 formatting rather than OGR own format.
    6285             :  *
    6286             :  * @return OGRERR_NONE if the operation succeeds, even if some values are
    6287             :  * not transferred, otherwise an error code.
    6288             :  */
    6289             : 
    6290        9230 : OGRErr OGRFeature::SetFrom(const OGRFeature *poSrcFeature, const int *panMap,
    6291             :                            int bForgiving, bool bUseISO8601ForDateTimeAsString)
    6292             : 
    6293             : {
    6294        9230 :     if (poSrcFeature == this)
    6295           0 :         return OGRERR_FAILURE;
    6296             : 
    6297        9230 :     SetFID(OGRNullFID);
    6298             : 
    6299             :     /* -------------------------------------------------------------------- */
    6300             :     /*      Set the geometry.                                               */
    6301             :     /* -------------------------------------------------------------------- */
    6302        9230 :     if (GetGeomFieldCount() == 1)
    6303             :     {
    6304        7790 :         const OGRGeomFieldDefn *poGFieldDefn = GetGeomFieldDefnRef(0);
    6305             : 
    6306        7790 :         int iSrc = poSrcFeature->GetGeomFieldIndex(poGFieldDefn->GetNameRef());
    6307        7790 :         if (iSrc >= 0)
    6308        6434 :             SetGeomField(0, poSrcFeature->GetGeomFieldRef(iSrc));
    6309             :         else
    6310             :             // Whatever the geometry field names are.  For backward
    6311             :             // compatibility.
    6312        1356 :             SetGeomField(0, poSrcFeature->GetGeomFieldRef(0));
    6313             :     }
    6314             :     else
    6315             :     {
    6316        2247 :         for (int i = 0; i < GetGeomFieldCount(); i++)
    6317             :         {
    6318         807 :             const OGRGeomFieldDefn *poGFieldDefn = GetGeomFieldDefnRef(i);
    6319             : 
    6320             :             const int iSrc =
    6321         807 :                 poSrcFeature->GetGeomFieldIndex(poGFieldDefn->GetNameRef());
    6322         807 :             if (iSrc >= 0)
    6323         718 :                 SetGeomField(i, poSrcFeature->GetGeomFieldRef(iSrc));
    6324             :             else
    6325          89 :                 SetGeomField(i, nullptr);
    6326             :         }
    6327             :     }
    6328             : 
    6329             :     /* -------------------------------------------------------------------- */
    6330             :     /*      Copy feature style string.                                      */
    6331             :     /* -------------------------------------------------------------------- */
    6332        9230 :     SetStyleString(poSrcFeature->GetStyleString());
    6333             : 
    6334             :     /* -------------------------------------------------------------------- */
    6335             :     /*      Copy native data.                                               */
    6336             :     /* -------------------------------------------------------------------- */
    6337        9230 :     SetNativeData(poSrcFeature->GetNativeData());
    6338        9230 :     SetNativeMediaType(poSrcFeature->GetNativeMediaType());
    6339             : 
    6340             :     /* -------------------------------------------------------------------- */
    6341             :     /*      Set the fields by name.                                         */
    6342             :     /* -------------------------------------------------------------------- */
    6343             : 
    6344        9230 :     const OGRErr eErr = SetFieldsFrom(poSrcFeature, panMap, bForgiving,
    6345             :                                       bUseISO8601ForDateTimeAsString);
    6346        9230 :     if (eErr != OGRERR_NONE)
    6347           0 :         return eErr;
    6348             : 
    6349        9230 :     return OGRERR_NONE;
    6350             : }
    6351             : 
    6352             : /************************************************************************/
    6353             : /*                        OGR_F_SetFromWithMap()                        */
    6354             : /************************************************************************/
    6355             : 
    6356             : /**
    6357             :  * \brief Set one feature from another.
    6358             :  *
    6359             :  * Overwrite the contents of this feature from the geometry and attributes
    6360             :  * of another.  The hOtherFeature does not need to have the same
    6361             :  * OGRFeatureDefn.  Field values are copied according to the provided indices
    6362             :  * map. Field types do not have to exactly match.  OGR_F_SetField*() function
    6363             :  * conversion rules will be applied as needed. This is more efficient than
    6364             :  * OGR_F_SetFrom() in that this doesn't lookup the fields by their names.
    6365             :  * Particularly useful when the field names don't match.
    6366             :  *
    6367             :  * This function is the same as the C++ method OGRFeature::SetFrom().
    6368             :  *
    6369             :  * @param hFeat handle to the feature to set to.
    6370             :  * @param hOtherFeat handle to the feature from which geometry,
    6371             :  * and field values will be copied.
    6372             :  *
    6373             :  * @param panMap Array of the indices of the destination feature's fields
    6374             :  * stored at the corresponding index of the source feature's fields. A value of
    6375             :  * -1 should be used to ignore the source's field. The array should not be NULL
    6376             :  * and be as long as the number of fields in the source feature.
    6377             :  *
    6378             :  * @param bForgiving TRUE if the operation should continue despite lacking
    6379             :  * output fields matching some of the source fields.
    6380             :  *
    6381             :  * @return OGRERR_NONE if the operation succeeds, even if some values are
    6382             :  * not transferred, otherwise an error code.
    6383             :  */
    6384             : 
    6385          10 : OGRErr OGR_F_SetFromWithMap(OGRFeatureH hFeat, OGRFeatureH hOtherFeat,
    6386             :                             int bForgiving, const int *panMap)
    6387             : 
    6388             : {
    6389          10 :     VALIDATE_POINTER1(hFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
    6390          10 :     VALIDATE_POINTER1(hOtherFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
    6391          10 :     VALIDATE_POINTER1(panMap, "OGR_F_SetFrom", OGRERR_FAILURE);
    6392             : 
    6393          20 :     return OGRFeature::FromHandle(hFeat)->SetFrom(
    6394          20 :         OGRFeature::FromHandle(hOtherFeat), panMap, bForgiving);
    6395             : }
    6396             : 
    6397             : /************************************************************************/
    6398             : /*                           SetFieldsFrom()                            */
    6399             : /************************************************************************/
    6400             : 
    6401             : /**
    6402             :  * \brief Set fields from another feature.
    6403             :  *
    6404             :  * Overwrite the fields of this feature from the attributes of
    6405             :  * another. The FID and the style string are not set. The poSrcFeature
    6406             :  * does not need to have the same OGRFeatureDefn.  Field values are
    6407             :  * copied according to the provided indices map. Field types do not
    6408             :  * have to exactly match.  SetField() method conversion rules will be
    6409             :  * applied as needed. This is more efficient than OGR_F_SetFrom() in
    6410             :  * that this doesn't lookup the fields by their names.  Particularly
    6411             :  * useful when the field names don't match.
    6412             :  *
    6413             :  * @param poSrcFeature the feature from which geometry, and field values will
    6414             :  * be copied.
    6415             :  *
    6416             :  * @param panMap Array of the indices of the feature's fields
    6417             :  * stored at the corresponding index of the source feature's fields. A value of
    6418             :  * -1 should be used to ignore the source's field. The array should not be NULL
    6419             :  * and be as long as the number of fields in the source feature.
    6420             :  *
    6421             :  * @param bForgiving TRUE if the operation should continue despite lacking
    6422             :  * output fields matching some of the source fields.
    6423             :  *
    6424             :  * @param bUseISO8601ForDateTimeAsString true if datetime fields
    6425             :  * converted to string should use ISO8601 formatting rather than OGR own format.
    6426             :  *
    6427             :  * @return OGRERR_NONE if the operation succeeds, even if some values are
    6428             :  * not transferred, otherwise an error code.
    6429             :  */
    6430             : 
    6431       11097 : OGRErr OGRFeature::SetFieldsFrom(const OGRFeature *poSrcFeature,
    6432             :                                  const int *panMap, int bForgiving,
    6433             :                                  bool bUseISO8601ForDateTimeAsString)
    6434             : 
    6435             : {
    6436       11097 :     const int nSrcFieldCount = poSrcFeature->poDefn->GetFieldCountUnsafe();
    6437       11097 :     const int nFieldCount = poDefn->GetFieldCountUnsafe();
    6438      117481 :     for (int iField = 0; iField < nSrcFieldCount; iField++)
    6439             :     {
    6440      106384 :         const int iDstField = panMap[iField];
    6441             : 
    6442      106384 :         if (iDstField < 0)
    6443        3523 :             continue;
    6444             : 
    6445      102861 :         if (nFieldCount <= iDstField)
    6446           0 :             return OGRERR_FAILURE;
    6447             : 
    6448      102861 :         if (!poSrcFeature->IsFieldSetUnsafe(iField))
    6449             :         {
    6450        9476 :             UnsetField(iDstField);
    6451        9476 :             continue;
    6452             :         }
    6453             : 
    6454       93385 :         if (poSrcFeature->IsFieldNullUnsafe(iField))
    6455             :         {
    6456        1751 :             SetFieldNull(iDstField);
    6457        1751 :             continue;
    6458             :         }
    6459             : 
    6460             :         const auto eSrcType =
    6461       91634 :             poSrcFeature->poDefn->GetFieldDefnUnsafe(iField)->GetType();
    6462       91634 :         const auto eDstType = poDefn->GetFieldDefnUnsafe(iDstField)->GetType();
    6463       91634 :         if (eSrcType == eDstType)
    6464             :         {
    6465       88581 :             if (eSrcType == OFTInteger)
    6466             :             {
    6467       30735 :                 SetFieldSameTypeUnsafe(
    6468             :                     iDstField, poSrcFeature->GetFieldAsIntegerUnsafe(iField));
    6469       30735 :                 continue;
    6470             :             }
    6471       57846 :             if (eSrcType == OFTInteger64)
    6472             :             {
    6473        3304 :                 SetFieldSameTypeUnsafe(
    6474             :                     iDstField, poSrcFeature->GetFieldAsInteger64Unsafe(iField));
    6475        3304 :                 continue;
    6476             :             }
    6477       54542 :             if (eSrcType == OFTReal)
    6478             :             {
    6479       13344 :                 SetFieldSameTypeUnsafe(
    6480             :                     iDstField, poSrcFeature->GetFieldAsDoubleUnsafe(iField));
    6481       13344 :                 continue;
    6482             :             }
    6483       41198 :             if (eSrcType == OFTString)
    6484             :             {
    6485       40409 :                 if (IsFieldSetAndNotNullUnsafe(iDstField))
    6486        1505 :                     CPLFree(pauFields[iDstField].String);
    6487             : 
    6488       40409 :                 SetFieldSameTypeUnsafe(
    6489             :                     iDstField,
    6490             :                     VSI_STRDUP_VERBOSE(
    6491             :                         poSrcFeature->GetFieldAsStringUnsafe(iField)));
    6492       40409 :                 continue;
    6493             :             }
    6494             :         }
    6495             : 
    6496             :         // Check if we must convert list types to JSON
    6497        3842 :         if (eDstType == OFTString)
    6498             :         {
    6499             :             const auto eDstSubType =
    6500          61 :                 poDefn->GetFieldDefnUnsafe(iDstField)->GetSubType();
    6501          61 :             if (eDstSubType == OFSTJSON &&
    6502          17 :                 (eSrcType == OFTIntegerList || eSrcType == OFTInteger64List ||
    6503           6 :                  eSrcType == OFTRealList || eSrcType == OFTStringList))
    6504             :             {
    6505          26 :                 char *pszVal = poSrcFeature->GetFieldAsSerializedJSon(iField);
    6506          26 :                 if (pszVal)
    6507             :                 {
    6508          26 :                     SetField(iDstField, pszVal);
    6509          26 :                     CPLFree(pszVal);
    6510          26 :                     continue;
    6511             :                 }
    6512             :             }
    6513             :         }
    6514             : 
    6515        3816 :         switch (eSrcType)
    6516             :         {
    6517        1205 :             case OFTInteger:
    6518        1205 :                 SetField(iDstField,
    6519             :                          poSrcFeature->GetFieldAsIntegerUnsafe(iField));
    6520        1205 :                 break;
    6521             : 
    6522        1613 :             case OFTInteger64:
    6523        1613 :                 SetField(iDstField,
    6524             :                          poSrcFeature->GetFieldAsInteger64Unsafe(iField));
    6525        1613 :                 break;
    6526             : 
    6527          25 :             case OFTReal:
    6528          25 :                 SetField(iDstField,
    6529             :                          poSrcFeature->GetFieldAsDoubleUnsafe(iField));
    6530          25 :                 break;
    6531             : 
    6532          86 :             case OFTString:
    6533          86 :                 SetField(iDstField,
    6534             :                          poSrcFeature->GetFieldAsStringUnsafe(iField));
    6535          86 :                 break;
    6536             : 
    6537         270 :             case OFTIntegerList:
    6538             :             {
    6539         270 :                 if (eDstType == OFTString)
    6540             :                 {
    6541           2 :                     SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
    6542             :                 }
    6543             :                 else
    6544             :                 {
    6545         268 :                     int nCount = 0;
    6546             :                     const int *panValues =
    6547         268 :                         poSrcFeature->GetFieldAsIntegerList(iField, &nCount);
    6548         268 :                     SetField(iDstField, nCount, panValues);
    6549             :                 }
    6550             :             }
    6551         270 :             break;
    6552             : 
    6553          47 :             case OFTInteger64List:
    6554             :             {
    6555          47 :                 if (eDstType == OFTString)
    6556             :                 {
    6557           1 :                     SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
    6558             :                 }
    6559             :                 else
    6560             :                 {
    6561          46 :                     int nCount = 0;
    6562             :                     const GIntBig *panValues =
    6563          46 :                         poSrcFeature->GetFieldAsInteger64List(iField, &nCount);
    6564          46 :                     SetField(iDstField, nCount, panValues);
    6565             :                 }
    6566             :             }
    6567          47 :             break;
    6568             : 
    6569          86 :             case OFTRealList:
    6570             :             {
    6571          86 :                 if (eDstType == OFTString)
    6572             :                 {
    6573           2 :                     SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
    6574             :                 }
    6575             :                 else
    6576             :                 {
    6577          84 :                     int nCount = 0;
    6578             :                     const double *padfValues =
    6579          84 :                         poSrcFeature->GetFieldAsDoubleList(iField, &nCount);
    6580          84 :                     SetField(iDstField, nCount, padfValues);
    6581             :                 }
    6582             :             }
    6583          86 :             break;
    6584             : 
    6585         412 :             case OFTDate:
    6586             :             case OFTDateTime:
    6587             :             case OFTTime:
    6588             :             {
    6589         412 :                 if (eDstType == OFTDate || eDstType == OFTTime ||
    6590             :                     eDstType == OFTDateTime)
    6591             :                 {
    6592         380 :                     SetField(iDstField, poSrcFeature->GetRawFieldRef(iField));
    6593             :                 }
    6594          32 :                 else if (eDstType == OFTString || eDstType == OFTStringList)
    6595             :                 {
    6596          22 :                     SetField(iDstField,
    6597           4 :                              eSrcType == OFTDateTime &&
    6598             :                                      bUseISO8601ForDateTimeAsString
    6599           2 :                                  ? poSrcFeature->GetFieldAsISO8601DateTime(
    6600             :                                        iField, nullptr)
    6601           9 :                                  : poSrcFeature->GetFieldAsString(iField));
    6602             :                 }
    6603          21 :                 else if (!bForgiving)
    6604           0 :                     return OGRERR_FAILURE;
    6605         412 :                 break;
    6606             :             }
    6607             : 
    6608          72 :             default:
    6609             :             {
    6610          72 :                 if (eSrcType == eDstType)
    6611             :                 {
    6612          47 :                     SetField(iDstField, poSrcFeature->GetRawFieldRef(iField));
    6613             :                 }
    6614          25 :                 else if (eDstType == OFTString || eDstType == OFTStringList)
    6615             :                 {
    6616           6 :                     SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
    6617             :                 }
    6618          19 :                 else if (!bForgiving)
    6619           0 :                     return OGRERR_FAILURE;
    6620          72 :                 break;
    6621             :             }
    6622             :         }
    6623             :     }
    6624             : 
    6625       11097 :     return OGRERR_NONE;
    6626             : }
    6627             : 
    6628             : /************************************************************************/
    6629             : /*                           GetStyleString()                           */
    6630             : /************************************************************************/
    6631             : 
    6632             : /**
    6633             :  * \brief Fetch style string for this feature.
    6634             :  *
    6635             :  * Set the OGR Feature Style Specification for details on the format of
    6636             :  * this string, and ogr_featurestyle.h for services available to parse it.
    6637             :  *
    6638             :  * This method is the same as the C function OGR_F_GetStyleString().
    6639             :  *
    6640             :  * @return a reference to a representation in string format, or NULL if
    6641             :  * there isn't one.
    6642             :  */
    6643             : 
    6644       61196 : const char *OGRFeature::GetStyleString() const
    6645             : {
    6646       61196 :     if (m_pszStyleString)
    6647        8731 :         return m_pszStyleString;
    6648             : 
    6649       52465 :     const int iStyleFieldIndex = GetFieldIndex("OGR_STYLE");
    6650       52465 :     if (iStyleFieldIndex >= 0)
    6651          62 :         return GetFieldAsString(iStyleFieldIndex);
    6652             : 
    6653       52403 :     return nullptr;
    6654             : }
    6655             : 
    6656             : /************************************************************************/
    6657             : /*                        OGR_F_GetStyleString()                        */
    6658             : /************************************************************************/
    6659             : 
    6660             : /**
    6661             :  * \brief Fetch style string for this feature.
    6662             :  *
    6663             :  * Set the OGR Feature Style Specification for details on the format of
    6664             :  * this string, and ogr_featurestyle.h for services available to parse it.
    6665             :  *
    6666             :  * This function is the same as the C++ method OGRFeature::GetStyleString().
    6667             :  *
    6668             :  * @param hFeat handle to the feature to get the style from.
    6669             :  * @return a reference to a representation in string format, or NULL if
    6670             :  * there isn't one.
    6671             :  */
    6672             : 
    6673        1585 : const char *OGR_F_GetStyleString(OGRFeatureH hFeat)
    6674             : {
    6675        1585 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetStyleString", nullptr);
    6676             : 
    6677        1585 :     return OGRFeature::FromHandle(hFeat)->GetStyleString();
    6678             : }
    6679             : 
    6680             : /************************************************************************/
    6681             : /*                           SetStyleString()                           */
    6682             : /************************************************************************/
    6683             : 
    6684             : /**
    6685             :  * \brief Set feature style string.
    6686             :  *
    6687             :  * This method operates the same as OGRFeature::SetStyleStringDirectly() except
    6688             :  * that it does not assume ownership of the passed string, but instead makes a
    6689             :  * copy of it.
    6690             :  *
    6691             :  * This method is the same as the C function OGR_F_SetStyleString().
    6692             :  *
    6693             :  * @param pszString the style string to apply to this feature, cannot be NULL.
    6694             :  */
    6695             : 
    6696      339047 : void OGRFeature::SetStyleString(const char *pszString)
    6697             : {
    6698      339047 :     if (m_pszStyleString)
    6699             :     {
    6700        2364 :         CPLFree(m_pszStyleString);
    6701        2364 :         m_pszStyleString = nullptr;
    6702             :     }
    6703             : 
    6704      339047 :     if (pszString)
    6705      324476 :         m_pszStyleString = VSI_STRDUP_VERBOSE(pszString);
    6706      339047 : }
    6707             : 
    6708             : /************************************************************************/
    6709             : /*                        OGR_F_SetStyleString()                        */
    6710             : /************************************************************************/
    6711             : 
    6712             : /**
    6713             :  * \brief Set feature style string.
    6714             :  *
    6715             :  * This method operates the same as OGR_F_SetStyleStringDirectly() except that it
    6716             :  * does not assume ownership of the passed string, but instead makes a copy of
    6717             :  * it.
    6718             :  *
    6719             :  * This function is the same as the C++ method OGRFeature::SetStyleString().
    6720             :  *
    6721             :  * @param hFeat handle to the feature to set style to.
    6722             :  * @param pszStyle the style string to apply to this feature, cannot be NULL.
    6723             :  */
    6724             : 
    6725          89 : void OGR_F_SetStyleString(OGRFeatureH hFeat, const char *pszStyle)
    6726             : 
    6727             : {
    6728          89 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleString");
    6729             : 
    6730          89 :     OGRFeature::FromHandle(hFeat)->SetStyleString(pszStyle);
    6731             : }
    6732             : 
    6733             : /************************************************************************/
    6734             : /*                       SetStyleStringDirectly()                       */
    6735             : /************************************************************************/
    6736             : 
    6737             : /**
    6738             :  * \brief Set feature style string.
    6739             :  *
    6740             :  * This method operates the same as OGRFeature::SetStyleString() except that it
    6741             :  * assumes ownership of the passed string.
    6742             :  *
    6743             :  * This method is the same as the C function OGR_F_SetStyleStringDirectly().
    6744             :  *
    6745             :  * @param pszString the style string to apply to this feature, cannot be NULL.
    6746             :  */
    6747             : 
    6748           0 : void OGRFeature::SetStyleStringDirectly(char *pszString)
    6749             : {
    6750           0 :     CPLFree(m_pszStyleString);
    6751           0 :     m_pszStyleString = pszString;
    6752           0 : }
    6753             : 
    6754             : /************************************************************************/
    6755             : /*                    OGR_F_SetStyleStringDirectly()                    */
    6756             : /************************************************************************/
    6757             : 
    6758             : /**
    6759             :  * \brief Set feature style string.
    6760             :  *
    6761             :  * This method operates the same as OGR_F_SetStyleString() except that it assumes
    6762             :  * ownership of the passed string.
    6763             :  *
    6764             :  * This function is the same as the C++ method
    6765             :  * OGRFeature::SetStyleStringDirectly().
    6766             :  *
    6767             :  * @param hFeat handle to the feature to set style to.
    6768             :  * @param pszStyle the style string to apply to this feature, cannot be NULL.
    6769             :  */
    6770             : 
    6771           0 : void OGR_F_SetStyleStringDirectly(OGRFeatureH hFeat, char *pszStyle)
    6772             : 
    6773             : {
    6774           0 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleStringDirectly");
    6775             : 
    6776           0 :     OGRFeature::FromHandle(hFeat)->SetStyleStringDirectly(pszStyle);
    6777             : }
    6778             : 
    6779             : //************************************************************************/
    6780             : /*                           SetStyleTable()                            */
    6781             : /************************************************************************/
    6782             : 
    6783             : /** Set style table.
    6784             :  * @param poStyleTable new style table (will be cloned)
    6785             :  */
    6786           0 : void OGRFeature::SetStyleTable(OGRStyleTable *poStyleTable)
    6787             : {
    6788           0 :     if (m_poStyleTable)
    6789           0 :         delete m_poStyleTable;
    6790           0 :     m_poStyleTable = poStyleTable ? poStyleTable->Clone() : nullptr;
    6791           0 : }
    6792             : 
    6793             : //************************************************************************/
    6794             : /*                       SetStyleTableDirectly()                        */
    6795             : /************************************************************************/
    6796             : 
    6797             : /** Set style table.
    6798             :  * @param poStyleTable new style table (ownership transferred to the object)
    6799             :  */
    6800           0 : void OGRFeature::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
    6801             : {
    6802           0 :     if (m_poStyleTable)
    6803           0 :         delete m_poStyleTable;
    6804           0 :     m_poStyleTable = poStyleTable;
    6805           0 : }
    6806             : 
    6807             : //! @cond Doxygen_Suppress
    6808             : 
    6809             : /************************************************************************/
    6810             : /*                            RemapFields()                             */
    6811             : /*                                                                      */
    6812             : /*      This is used to transform a feature "in place" from one         */
    6813             : /*      feature defn to another with minimum work.                      */
    6814             : /************************************************************************/
    6815             : 
    6816          50 : OGRErr OGRFeature::RemapFields(const OGRFeatureDefn *poNewDefn,
    6817             :                                const int *panRemapSource)
    6818             : 
    6819             : {
    6820          50 :     if (poNewDefn == nullptr)
    6821          50 :         poNewDefn = poDefn;
    6822             : 
    6823          50 :     const int nNewFieldCount = poNewDefn->GetFieldCount();
    6824             :     OGRField *pauNewFields =
    6825          50 :         static_cast<OGRField *>(CPLCalloc(nNewFieldCount, sizeof(OGRField)));
    6826             : 
    6827          50 :     const int nFieldCount = poDefn->GetFieldCount();
    6828         318 :     for (int iDstField = 0; iDstField < nFieldCount; iDstField++)
    6829             :     {
    6830         268 :         if (panRemapSource[iDstField] == -1)
    6831             :         {
    6832          16 :             OGR_RawField_SetUnset(&pauNewFields[iDstField]);
    6833             :         }
    6834             :         else
    6835             :         {
    6836         252 :             memcpy(pauNewFields + iDstField,
    6837         252 :                    pauFields + panRemapSource[iDstField], sizeof(OGRField));
    6838             :         }
    6839             :     }
    6840             : 
    6841             :     // We really should be freeing memory for old columns that
    6842             :     // are no longer present.  We don't for now because it is a bit messy
    6843             :     // and would take too long to test.
    6844             : 
    6845             :     /* -------------------------------------------------------------------- */
    6846             :     /*      Apply new definition and fields.                                */
    6847             :     /* -------------------------------------------------------------------- */
    6848          50 :     CPLFree(pauFields);
    6849          50 :     pauFields = pauNewFields;
    6850             : 
    6851          50 :     poDefn = poNewDefn;
    6852             : 
    6853          50 :     return OGRERR_NONE;
    6854             : }
    6855             : 
    6856             : /************************************************************************/
    6857             : /*                            AppendField()                             */
    6858             : /*                                                                      */
    6859             : /*      This is used to transform a feature "in place" by appending     */
    6860             : /*      an unset field.                                                 */
    6861             : /************************************************************************/
    6862             : 
    6863         573 : void OGRFeature::AppendField()
    6864             : {
    6865         573 :     const int nFieldCount = poDefn->GetFieldCountUnsafe();
    6866         573 :     pauFields = static_cast<OGRField *>(
    6867         573 :         CPLRealloc(pauFields, nFieldCount * sizeof(OGRField)));
    6868         573 :     OGR_RawField_SetUnset(&pauFields[nFieldCount - 1]);
    6869         573 : }
    6870             : 
    6871             : /************************************************************************/
    6872             : /*                        RemapGeomFields()                             */
    6873             : /*                                                                      */
    6874             : /*      This is used to transform a feature "in place" from one         */
    6875             : /*      feature defn to another with minimum work.                      */
    6876             : /************************************************************************/
    6877             : 
    6878           3 : OGRErr OGRFeature::RemapGeomFields(const OGRFeatureDefn *poNewDefn,
    6879             :                                    const int *panRemapSource)
    6880             : 
    6881             : {
    6882           3 :     if (poNewDefn == nullptr)
    6883           3 :         poNewDefn = poDefn;
    6884             : 
    6885             :     OGRGeometry **papoNewGeomFields = static_cast<OGRGeometry **>(
    6886           3 :         CPLCalloc(poNewDefn->GetGeomFieldCount(), sizeof(OGRGeometry *)));
    6887             : 
    6888           9 :     for (int iDstField = 0; iDstField < poDefn->GetGeomFieldCount();
    6889             :          iDstField++)
    6890             :     {
    6891           6 :         if (panRemapSource[iDstField] == -1)
    6892             :         {
    6893           3 :             papoNewGeomFields[iDstField] = nullptr;
    6894             :         }
    6895             :         else
    6896             :         {
    6897           3 :             papoNewGeomFields[iDstField] =
    6898           3 :                 papoGeometries[panRemapSource[iDstField]];
    6899             :         }
    6900             :     }
    6901             : 
    6902             :     // We really should be freeing memory for old columns that
    6903             :     // are no longer present.  We don't for now because it is a bit messy
    6904             :     // and would take too long to test.
    6905             : 
    6906             :     /* -------------------------------------------------------------------- */
    6907             :     /*      Apply new definition and fields.                                */
    6908             :     /* -------------------------------------------------------------------- */
    6909           3 :     CPLFree(papoGeometries);
    6910           3 :     papoGeometries = papoNewGeomFields;
    6911             : 
    6912           3 :     poDefn = poNewDefn;
    6913             : 
    6914           3 :     return OGRERR_NONE;
    6915             : }
    6916             : 
    6917             : //! @endcond
    6918             : 
    6919             : /************************************************************************/
    6920             : /*                        OGR_F_GetStyleTable()                         */
    6921             : /************************************************************************/
    6922             : 
    6923           0 : OGRStyleTableH OGR_F_GetStyleTable(OGRFeatureH hFeat)
    6924             : 
    6925             : {
    6926           0 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetStyleTable", nullptr);
    6927             : 
    6928             :     return reinterpret_cast<OGRStyleTableH>(
    6929           0 :         OGRFeature::FromHandle(hFeat)->GetStyleTable());
    6930             : }
    6931             : 
    6932             : /************************************************************************/
    6933             : /*                    OGR_F_SetStyleTableDirectly()                     */
    6934             : /************************************************************************/
    6935             : 
    6936           0 : void OGR_F_SetStyleTableDirectly(OGRFeatureH hFeat, OGRStyleTableH hStyleTable)
    6937             : 
    6938             : {
    6939           0 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleTableDirectly");
    6940             : 
    6941           0 :     OGRFeature::FromHandle(hFeat)->SetStyleTableDirectly(
    6942           0 :         reinterpret_cast<OGRStyleTable *>(hStyleTable));
    6943             : }
    6944             : 
    6945             : /************************************************************************/
    6946             : /*                        OGR_F_SetStyleTable()                         */
    6947             : /************************************************************************/
    6948             : 
    6949           0 : void OGR_F_SetStyleTable(OGRFeatureH hFeat, OGRStyleTableH hStyleTable)
    6950             : 
    6951             : {
    6952           0 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleTable");
    6953           0 :     VALIDATE_POINTER0(hStyleTable, "OGR_F_SetStyleTable");
    6954             : 
    6955           0 :     OGRFeature::FromHandle(hFeat)->SetStyleTable(
    6956           0 :         reinterpret_cast<OGRStyleTable *>(hStyleTable));
    6957             : }
    6958             : 
    6959             : /************************************************************************/
    6960             : /*                        FillUnsetWithDefault()                        */
    6961             : /************************************************************************/
    6962             : 
    6963             : /**
    6964             :  * \brief Fill unset fields with default values that might be defined.
    6965             :  *
    6966             :  * This method is the same as the C function OGR_F_FillUnsetWithDefault().
    6967             :  *
    6968             :  * @param bNotNullableOnly if we should fill only unset fields with a not-null
    6969             :  *                     constraint.
    6970             :  * @param papszOptions unused currently. Must be set to NULL.
    6971             :  */
    6972             : 
    6973      277532 : void OGRFeature::FillUnsetWithDefault(int bNotNullableOnly,
    6974             :                                       CPL_UNUSED CSLConstList papszOptions)
    6975             : {
    6976      277532 :     const int nFieldCount = poDefn->GetFieldCount();
    6977     4755770 :     for (int i = 0; i < nFieldCount; i++)
    6978             :     {
    6979     4478240 :         if (IsFieldSetUnsafe(i))
    6980     4476680 :             continue;
    6981        1557 :         const auto poFieldDefn = poDefn->GetFieldDefn(i);
    6982        1557 :         if (bNotNullableOnly && poFieldDefn->IsNullable())
    6983         109 :             continue;
    6984        1448 :         const char *pszDefault = poFieldDefn->GetDefault();
    6985        1448 :         OGRFieldType eType = poFieldDefn->GetType();
    6986        1448 :         if (pszDefault != nullptr)
    6987             :         {
    6988          48 :             if (eType == OFTDate || eType == OFTTime || eType == OFTDateTime)
    6989             :             {
    6990           9 :                 if (STARTS_WITH_CI(pszDefault, "CURRENT"))
    6991             :                 {
    6992           4 :                     time_t t = time(nullptr);
    6993             :                     struct tm brokendown;
    6994           4 :                     CPLUnixTimeToYMDHMS(t, &brokendown);
    6995           4 :                     SetField(i, brokendown.tm_year + 1900,
    6996           4 :                              brokendown.tm_mon + 1, brokendown.tm_mday,
    6997             :                              brokendown.tm_hour, brokendown.tm_min,
    6998           4 :                              static_cast<float>(brokendown.tm_sec), 100);
    6999             :                 }
    7000             :                 else
    7001             :                 {
    7002           5 :                     int nYear = 0;
    7003           5 :                     int nMonth = 0;
    7004           5 :                     int nDay = 0;
    7005           5 :                     int nHour = 0;
    7006           5 :                     int nMinute = 0;
    7007           5 :                     float fSecond = 0.0f;
    7008           5 :                     if (sscanf(pszDefault, "'%d/%d/%d %d:%d:%f'", &nYear,
    7009           5 :                                &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6)
    7010             :                     {
    7011           4 :                         SetField(i, nYear, nMonth, nDay, nHour, nMinute,
    7012             :                                  fSecond, 100);
    7013             :                     }
    7014           9 :                 }
    7015             :             }
    7016          39 :             else if (eType == OFTString && pszDefault[0] == '\'' &&
    7017           8 :                      pszDefault[strlen(pszDefault) - 1] == '\'')
    7018             :             {
    7019          16 :                 CPLString osDefault(pszDefault + 1);
    7020           8 :                 osDefault.pop_back();
    7021           8 :                 char *pszTmp = CPLUnescapeString(osDefault, nullptr, CPLES_SQL);
    7022           8 :                 SetField(i, pszTmp);
    7023          16 :                 CPLFree(pszTmp);
    7024             :             }
    7025          31 :             else if (!poFieldDefn->IsDefaultDriverSpecific())
    7026          13 :                 SetField(i, pszDefault);
    7027             :         }
    7028             :     }
    7029      277532 : }
    7030             : 
    7031             : /************************************************************************/
    7032             : /*                     OGR_F_FillUnsetWithDefault()                     */
    7033             : /************************************************************************/
    7034             : 
    7035             : /**
    7036             :  * \brief Fill unset fields with default values that might be defined.
    7037             :  *
    7038             :  * This function is the same as the C++ method
    7039             :  * OGRFeature::FillUnsetWithDefault().
    7040             :  *
    7041             :  * @param hFeat handle to the feature.
    7042             :  * @param bNotNullableOnly if we should fill only unset fields with a not-null
    7043             :  *                     constraint.
    7044             :  * @param papszOptions unused currently. Must be set to NULL.
    7045             :  */
    7046             : 
    7047           2 : void OGR_F_FillUnsetWithDefault(OGRFeatureH hFeat, int bNotNullableOnly,
    7048             :                                 CSLConstList papszOptions)
    7049             : 
    7050             : {
    7051           2 :     VALIDATE_POINTER0(hFeat, "OGR_F_FillUnsetWithDefault");
    7052             : 
    7053           2 :     OGRFeature::FromHandle(hFeat)->FillUnsetWithDefault(bNotNullableOnly,
    7054             :                                                         papszOptions);
    7055             : }
    7056             : 
    7057             : /************************************************************************/
    7058             : /*                              Validate()                              */
    7059             : /************************************************************************/
    7060             : 
    7061             : /**
    7062             :  * \brief Validate that a feature meets constraints of its schema.
    7063             :  *
    7064             :  * The scope of test is specified with the nValidateFlags parameter.
    7065             :  *
    7066             :  * Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width must be
    7067             :  * interpreted as the number of UTF-8 characters. Some drivers might interpret
    7068             :  * the width as the number of bytes instead. So this test is rather conservative
    7069             :  * (if it fails, then it will fail for all interpretations).
    7070             :  *
    7071             :  * This method is the same as the C function OGR_F_Validate().
    7072             :  *
    7073             :  * @param nValidateFlags OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
    7074             :  *                       OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and
    7075             :  *                       OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT,
    7076             :  *                       OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM with '|' operator
    7077             :  * @param bEmitError TRUE if a CPLError() must be emitted when a check fails
    7078             :  * @return TRUE if all enabled validation tests pass.
    7079             :  */
    7080             : 
    7081         470 : int OGRFeature::Validate(int nValidateFlags, int bEmitError) const
    7082             : 
    7083             : {
    7084         470 :     bool bRet = true;
    7085             : 
    7086         470 :     const int nGeomFieldCount = poDefn->GetGeomFieldCount();
    7087         900 :     for (int i = 0; i < nGeomFieldCount; i++)
    7088             :     {
    7089         430 :         if ((nValidateFlags & OGR_F_VAL_NULL) &&
    7090         860 :             !poDefn->GetGeomFieldDefn(i)->IsNullable() &&
    7091          12 :             GetGeomFieldRef(i) == nullptr)
    7092             :         {
    7093           3 :             bRet = false;
    7094           3 :             if (bEmitError)
    7095             :             {
    7096           3 :                 CPLError(
    7097             :                     CE_Failure, CPLE_AppDefined,
    7098             :                     "Geometry field %s has a NULL content which is not allowed",
    7099           3 :                     poDefn->GetGeomFieldDefn(i)->GetNameRef());
    7100             :             }
    7101             :         }
    7102         603 :         if ((nValidateFlags & OGR_F_VAL_GEOM_TYPE) &&
    7103         173 :             poDefn->GetGeomFieldDefn(i)->GetType() != wkbUnknown)
    7104             :         {
    7105         136 :             const OGRGeometry *poGeom = GetGeomFieldRef(i);
    7106         136 :             if (poGeom != nullptr)
    7107             :             {
    7108             :                 const OGRwkbGeometryType eType =
    7109         101 :                     poDefn->GetGeomFieldDefn(i)->GetType();
    7110         101 :                 const OGRwkbGeometryType eFType = poGeom->getGeometryType();
    7111         200 :                 if ((nValidateFlags & OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM) &&
    7112          99 :                     (wkbFlatten(eFType) == wkbFlatten(eType) ||
    7113          17 :                      wkbFlatten(eType) == wkbUnknown))
    7114             :                 {
    7115             :                     // Ok.
    7116             :                 }
    7117          32 :                 else if ((eType == wkbSetZ(wkbUnknown) && !wkbHasZ(eFType)) ||
    7118          16 :                          (eType != wkbSetZ(wkbUnknown) && eFType != eType))
    7119             :                 {
    7120          15 :                     bRet = false;
    7121          15 :                     if (bEmitError)
    7122             :                     {
    7123          30 :                         CPLError(CE_Failure, CPLE_AppDefined,
    7124             :                                  "Geometry field %s has a %s geometry whereas "
    7125             :                                  "%s is expected",
    7126          15 :                                  poDefn->GetGeomFieldDefn(i)->GetNameRef(),
    7127             :                                  OGRGeometryTypeToName(eFType),
    7128             :                                  OGRGeometryTypeToName(eType));
    7129             :                     }
    7130             :                 }
    7131             :             }
    7132             :         }
    7133             :     }
    7134         470 :     const int nFieldCount = poDefn->GetFieldCount();
    7135        1670 :     for (int i = 0; i < nFieldCount; i++)
    7136             :     {
    7137        1200 :         if ((nValidateFlags & OGR_F_VAL_NULL) &&
    7138        2403 :             !poDefn->GetFieldDefn(i)->IsNullable() && !IsFieldSet(i) &&
    7139           3 :             (!(nValidateFlags & OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT) ||
    7140           2 :              poDefn->GetFieldDefn(i)->GetDefault() == nullptr))
    7141             :         {
    7142           3 :             bRet = false;
    7143           3 :             if (bEmitError)
    7144             :             {
    7145           6 :                 CPLError(CE_Failure, CPLE_AppDefined,
    7146             :                          "Field %s.%s has a NULL content which is not allowed",
    7147           3 :                          poDefn->GetName(),
    7148           3 :                          poDefn->GetFieldDefn(i)->GetNameRef());
    7149             :             }
    7150             :         }
    7151         630 :         if ((nValidateFlags & OGR_F_VAL_WIDTH) &&
    7152         866 :             poDefn->GetFieldDefn(i)->GetWidth() > 0 &&
    7153         308 :             poDefn->GetFieldDefn(i)->GetType() == OFTString && IsFieldSet(i) &&
    7154        1902 :             CPLIsUTF8(GetFieldAsString(i), -1) &&
    7155          72 :             CPLStrlenUTF8Ex(GetFieldAsString(i)) >
    7156          72 :                 static_cast<size_t>(poDefn->GetFieldDefn(i)->GetWidth()))
    7157             :         {
    7158           1 :             bRet = false;
    7159           1 :             if (bEmitError)
    7160             :             {
    7161           3 :                 CPLError(
    7162             :                     CE_Failure, CPLE_AppDefined,
    7163             :                     "Field %s.%s has %" PRIu64 " UTF-8 characters whereas "
    7164             :                     "a maximum of %d is allowed",
    7165           1 :                     poDefn->GetName(), poDefn->GetFieldDefn(i)->GetNameRef(),
    7166           1 :                     static_cast<uint64_t>(CPLStrlenUTF8Ex(GetFieldAsString(i))),
    7167           1 :                     poDefn->GetFieldDefn(i)->GetWidth());
    7168             :             }
    7169             :         }
    7170             :     }
    7171             : 
    7172         470 :     return bRet;
    7173             : }
    7174             : 
    7175             : /************************************************************************/
    7176             : /*                           OGR_F_Validate()                           */
    7177             : /************************************************************************/
    7178             : 
    7179             : /**
    7180             :  * \brief Validate that a feature meets constraints of its schema.
    7181             :  *
    7182             :  * The scope of test is specified with the nValidateFlags parameter.
    7183             :  *
    7184             :  * Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width must be
    7185             :  * interpreted as the number of UTF-8 characters. Some drivers might interpret
    7186             :  * the width as the number of bytes instead. So this test is rather conservative
    7187             :  * (if it fails, then it will fail for all interpretations).
    7188             :  *
    7189             :  * This function is the same as the C++ method
    7190             :  * OGRFeature::Validate().
    7191             :  *
    7192             :  * @param hFeat handle to the feature to validate.
    7193             :  * @param nValidateFlags OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
    7194             :  *                       OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and
    7195             :  *                       OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT with '|' operator
    7196             :  * @param bEmitError TRUE if a CPLError() must be emitted when a check fails
    7197             :  * @return TRUE if all enabled validation tests pass.
    7198             :  */
    7199             : 
    7200          10 : int OGR_F_Validate(OGRFeatureH hFeat, int nValidateFlags, int bEmitError)
    7201             : 
    7202             : {
    7203          10 :     VALIDATE_POINTER1(hFeat, "OGR_F_Validate", FALSE);
    7204             : 
    7205          10 :     return OGRFeature::FromHandle(hFeat)->Validate(nValidateFlags, bEmitError);
    7206             : }
    7207             : 
    7208             : /************************************************************************/
    7209             : /*                           GetNativeData()                            */
    7210             : /************************************************************************/
    7211             : 
    7212             : /**
    7213             :  * \fn const char* OGRFeature::GetNativeData() const;
    7214             :  *
    7215             :  * \brief Returns the native data for the feature.
    7216             :  *
    7217             :  * The native data is the representation in a "natural" form that comes from
    7218             :  * the driver that created this feature, or that is aimed at an output driver.
    7219             :  * The native data may be in different format, which is indicated by
    7220             :  * GetNativeMediaType().
    7221             :  *
    7222             :  * Note that most drivers do not support storing the native data in the feature
    7223             :  * object, and if they do, generally the NATIVE_DATA open option must be passed
    7224             :  * at dataset opening.
    7225             :  *
    7226             :  * The "native data" does not imply it is something more performant or powerful
    7227             :  * than what can be obtained with the rest of the API, but it may be useful in
    7228             :  * round-tripping scenarios where some characteristics of the underlying format
    7229             :  * are not captured otherwise by the OGR abstraction.
    7230             :  *
    7231             :  * This function is the same as the C function
    7232             :  * OGR_F_GetNativeData().
    7233             :  *
    7234             :  * @return a string with the native data, or NULL if there is none.
    7235             :  *
    7236             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7237             :  */
    7238             : 
    7239             : /************************************************************************/
    7240             : /*                        OGR_F_GetNativeData()                         */
    7241             : /************************************************************************/
    7242             : 
    7243             : /**
    7244             :  * \brief Returns the native data for the feature.
    7245             :  *
    7246             :  * The native data is the representation in a "natural" form that comes from
    7247             :  * the driver that created this feature, or that is aimed at an output driver.
    7248             :  * The native data may be in different format, which is indicated by
    7249             :  * OGR_F_GetNativeMediaType().
    7250             :  *
    7251             :  * Note that most drivers do not support storing the native data in the feature
    7252             :  * object, and if they do, generally the NATIVE_DATA open option must be passed
    7253             :  * at dataset opening.
    7254             :  *
    7255             :  * The "native data" does not imply it is something more performant or powerful
    7256             :  * than what can be obtained with the rest of the API, but it may be useful in
    7257             :  * round-tripping scenarios where some characteristics of the underlying format
    7258             :  * are not captured otherwise by the OGR abstraction.
    7259             :  *
    7260             :  * This function is the same as the C++ method
    7261             :  * OGRFeature::GetNativeData().
    7262             :  *
    7263             :  * @param hFeat handle to the feature.
    7264             :  * @return a string with the native data, or NULL if there is none.
    7265             :  *
    7266             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7267             :  */
    7268             : 
    7269           9 : const char *OGR_F_GetNativeData(OGRFeatureH hFeat)
    7270             : 
    7271             : {
    7272           9 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetNativeData", nullptr);
    7273             : 
    7274           9 :     return OGRFeature::FromHandle(hFeat)->GetNativeData();
    7275             : }
    7276             : 
    7277             : /************************************************************************/
    7278             : /*                         GetNativeMediaType()                         */
    7279             : /************************************************************************/
    7280             : 
    7281             : /**
    7282             :  * \fn const char* OGRFeature::GetNativeMediaType() const;
    7283             :  *
    7284             :  * \brief Returns the native media type for the feature.
    7285             :  *
    7286             :  * The native media type is the identifier for the format of the native data.
    7287             :  * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
    7288             :  * e.g. "application/vnd.geo+json" for JSon.
    7289             :  *
    7290             :  * This function is the same as the C function
    7291             :  * OGR_F_GetNativeMediaType().
    7292             :  *
    7293             :  * @return a string with the native media type, or NULL if there is none.
    7294             :  *
    7295             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7296             :  */
    7297             : 
    7298             : /************************************************************************/
    7299             : /*                      OGR_F_GetNativeMediaType()                      */
    7300             : /************************************************************************/
    7301             : 
    7302             : /**
    7303             :  * \brief Returns the native media type for the feature.
    7304             :  *
    7305             :  * The native media type is the identifier for the format of the native data.
    7306             :  * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
    7307             :  * e.g. "application/vnd.geo+json" for JSon.
    7308             :  *
    7309             :  * This function is the same as the C function
    7310             :  * OGR_F_GetNativeMediaType().
    7311             :  *
    7312             :  * @param hFeat handle to the feature.
    7313             :  * @return a string with the native media type, or NULL if there is none.
    7314             :  *
    7315             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7316             :  */
    7317             : 
    7318           9 : const char *OGR_F_GetNativeMediaType(OGRFeatureH hFeat)
    7319             : {
    7320           9 :     VALIDATE_POINTER1(hFeat, "OGR_F_GetNativeMediaType", nullptr);
    7321             : 
    7322           9 :     return OGRFeature::FromHandle(hFeat)->GetNativeMediaType();
    7323             : }
    7324             : 
    7325             : /************************************************************************/
    7326             : /*                           SetNativeData()                            */
    7327             : /************************************************************************/
    7328             : 
    7329             : /**
    7330             :  * \brief Sets the native data for the feature.
    7331             :  *
    7332             :  * The native data is the representation in a "natural" form that comes from
    7333             :  * the driver that created this feature, or that is aimed at an output driver.
    7334             :  * The native data may be in different format, which is indicated by
    7335             :  * GetNativeMediaType().
    7336             :  *
    7337             :  * This function is the same as the C function
    7338             :  * OGR_F_SetNativeData().
    7339             :  *
    7340             :  * @param pszNativeData a string with the native data, or NULL if there is none.
    7341             :  *
    7342             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7343             :  */
    7344             : 
    7345       14969 : void OGRFeature::SetNativeData(const char *pszNativeData)
    7346             : {
    7347       14969 :     CPLFree(m_pszNativeData);
    7348       14969 :     m_pszNativeData =
    7349       14969 :         pszNativeData ? VSI_STRDUP_VERBOSE(pszNativeData) : nullptr;
    7350       14969 : }
    7351             : 
    7352             : /************************************************************************/
    7353             : /*                        OGR_F_SetNativeData()                         */
    7354             : /************************************************************************/
    7355             : 
    7356             : /**
    7357             :  * \brief Sets the native data for the feature.
    7358             :  *
    7359             :  * The native data is the representation in a "natural" form that comes from
    7360             :  * the driver that created this feature, or that is aimed at an output driver.
    7361             :  * The native data may be in different format, which is indicated by
    7362             :  * OGR_F_GetNativeMediaType().
    7363             :  *
    7364             :  * This function is the same as the C++ method
    7365             :  * OGRFeature::SetNativeData().
    7366             :  *
    7367             :  * @param hFeat handle to the feature.
    7368             :  * @param pszNativeData a string with the native data, or NULL if there is none.
    7369             :  *
    7370             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7371             :  */
    7372             : 
    7373           4 : void OGR_F_SetNativeData(OGRFeatureH hFeat, const char *pszNativeData)
    7374             : {
    7375           4 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetNativeData");
    7376             : 
    7377           4 :     OGRFeature::FromHandle(hFeat)->SetNativeData(pszNativeData);
    7378             : }
    7379             : 
    7380             : /************************************************************************/
    7381             : /*                         SetNativeMediaType()                         */
    7382             : /************************************************************************/
    7383             : 
    7384             : /**
    7385             :  * \brief Sets the native media type for the feature.
    7386             :  *
    7387             :  * The native media type is the identifier for the format of the native data.
    7388             :  * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
    7389             :  * e.g. "application/vnd.geo+json" for JSon.
    7390             :  *
    7391             :  * This function is the same as the C function
    7392             :  * OGR_F_SetNativeMediaType().
    7393             :  *
    7394             :  * @param pszNativeMediaType a string with the native media type, or NULL if
    7395             :  * there is none.
    7396             :  *
    7397             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7398             :  */
    7399             : 
    7400       14969 : void OGRFeature::SetNativeMediaType(const char *pszNativeMediaType)
    7401             : {
    7402       14969 :     CPLFree(m_pszNativeMediaType);
    7403       14969 :     m_pszNativeMediaType =
    7404       14969 :         pszNativeMediaType ? VSI_STRDUP_VERBOSE(pszNativeMediaType) : nullptr;
    7405       14969 : }
    7406             : 
    7407             : /************************************************************************/
    7408             : /*                      OGR_F_SetNativeMediaType()                      */
    7409             : /************************************************************************/
    7410             : 
    7411             : /**
    7412             :  * \brief Sets the native media type for the feature.
    7413             :  *
    7414             :  * The native media type is the identifier for the format of the native data.
    7415             :  * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
    7416             :  * e.g. "application/vnd.geo+json" for JSon.
    7417             :  *
    7418             :  * This function is the same as the C++ method
    7419             :  * OGRFeature::SetNativeMediaType().
    7420             :  *
    7421             :  * @param hFeat handle to the feature.
    7422             :  * @param pszNativeMediaType a string with the native media type, or NULL if
    7423             :  * there is none.
    7424             :  *
    7425             :  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
    7426             :  */
    7427             : 
    7428           4 : void OGR_F_SetNativeMediaType(OGRFeatureH hFeat, const char *pszNativeMediaType)
    7429             : {
    7430           4 :     VALIDATE_POINTER0(hFeat, "OGR_F_SetNativeMediaType");
    7431             : 
    7432           4 :     OGRFeature::FromHandle(hFeat)->SetNativeMediaType(pszNativeMediaType);
    7433             : }
    7434             : 
    7435             : /************************************************************************/
    7436             : /*                        OGR_RawField_IsUnset()                        */
    7437             : /************************************************************************/
    7438             : 
    7439             : /**
    7440             :  * \brief Returns whether a raw field is unset.
    7441             :  *
    7442             :  * Note: this function is rather low-level and should be rarely used in client
    7443             :  * code. Use instead OGR_F_IsFieldSet().
    7444             :  *
    7445             :  * @param puField pointer to raw field.
    7446             :  */
    7447             : 
    7448     3741500 : int OGR_RawField_IsUnset(const OGRField *puField)
    7449             : {
    7450     5176590 :     return puField->Set.nMarker1 == OGRUnsetMarker &&
    7451     5176590 :            puField->Set.nMarker2 == OGRUnsetMarker &&
    7452     5176590 :            puField->Set.nMarker3 == OGRUnsetMarker;
    7453             : }
    7454             : 
    7455             : /************************************************************************/
    7456             : /*                        OGR_RawField_IsNull()                         */
    7457             : /************************************************************************/
    7458             : 
    7459             : /**
    7460             :  * \brief Returns whether a raw field is null.
    7461             :  *
    7462             :  * Note: this function is rather low-level and should be rarely used in client
    7463             :  * code. Use instead OGR_F_IsFieldNull().
    7464             :  *
    7465             :  * @param puField pointer to raw field.
    7466             :  */
    7467             : 
    7468     2293460 : int OGR_RawField_IsNull(const OGRField *puField)
    7469             : {
    7470     2298180 :     return puField->Set.nMarker1 == OGRNullMarker &&
    7471     2298180 :            puField->Set.nMarker2 == OGRNullMarker &&
    7472     2298180 :            puField->Set.nMarker3 == OGRNullMarker;
    7473             : }
    7474             : 
    7475             : /************************************************************************/
    7476             : /*                       OGR_RawField_SetUnset()                        */
    7477             : /************************************************************************/
    7478             : 
    7479             : /**
    7480             :  * \brief Mark a raw field as unset.
    7481             :  *
    7482             :  * This should be called on a un-initialized field. In particular this will not
    7483             :  * free any memory dynamically allocated.
    7484             :  *
    7485             :  * Note: this function is rather low-level and should be rarely used in client
    7486             :  * code. Use instead OGR_F_UnsetField().
    7487             :  *
    7488             :  * @param puField pointer to raw field.
    7489             :  */
    7490             : 
    7491      116088 : void OGR_RawField_SetUnset(OGRField *puField)
    7492             : {
    7493      116088 :     puField->Set.nMarker1 = OGRUnsetMarker;
    7494      116088 :     puField->Set.nMarker2 = OGRUnsetMarker;
    7495      116088 :     puField->Set.nMarker3 = OGRUnsetMarker;
    7496      116088 : }
    7497             : 
    7498             : /************************************************************************/
    7499             : /*                        OGR_RawField_SetNull()                        */
    7500             : /************************************************************************/
    7501             : 
    7502             : /**
    7503             :  * \brief Mark a raw field as null.
    7504             :  *
    7505             :  * This should be called on a un-initialized field. In particular this will not
    7506             :  * free any memory dynamically allocated.
    7507             :  *
    7508             :  * Note: this function is rather low-level and should be rarely used in client
    7509             :  * code. Use instead OGR_F_SetFieldNull().
    7510             :  *
    7511             :  * @param puField pointer to raw field.
    7512             :  */
    7513             : 
    7514       57151 : void OGR_RawField_SetNull(OGRField *puField)
    7515             : {
    7516       57151 :     puField->Set.nMarker1 = OGRNullMarker;
    7517       57151 :     puField->Set.nMarker2 = OGRNullMarker;
    7518       57151 :     puField->Set.nMarker3 = OGRNullMarker;
    7519       57151 : }
    7520             : 
    7521             : /************************************************************************/
    7522             : /*                      OGRFeatureUniquePtrDeleter                      */
    7523             : /************************************************************************/
    7524             : 
    7525             : //! @cond Doxygen_Suppress
    7526      166844 : void OGRFeatureUniquePtrDeleter::operator()(OGRFeature *poFeature) const
    7527             : {
    7528      166844 :     delete poFeature;
    7529      166844 : }
    7530             : 
    7531             : //! @endcond
    7532             : 
    7533             : namespace
    7534             : {
    7535             : // Implementation borrowed to OpenFileGDB
    7536             : 
    7537             : /************************************************************************/
    7538             : /*                             WriteUInt8()                             */
    7539             : /************************************************************************/
    7540             : 
    7541       11025 : inline void WriteUInt8(std::vector<GByte> &abyBuffer, uint8_t nVal)
    7542             : {
    7543       11025 :     abyBuffer.push_back(nVal);
    7544       11025 : }
    7545             : 
    7546             : /************************************************************************/
    7547             : /*                            WriteVarUInt()                            */
    7548             : /************************************************************************/
    7549             : 
    7550        5789 : inline void WriteVarUInt(std::vector<GByte> &abyBuffer, uint64_t nVal)
    7551             : {
    7552             :     while (true)
    7553             :     {
    7554        5789 :         if (nVal >= 0x80)
    7555             :         {
    7556          16 :             WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nVal & 0x7F)));
    7557          16 :             nVal >>= 7;
    7558             :         }
    7559             :         else
    7560             :         {
    7561        5773 :             WriteUInt8(abyBuffer, static_cast<uint8_t>(nVal));
    7562        5773 :             break;
    7563             :         }
    7564             :     }
    7565        5773 : }
    7566             : 
    7567             : /************************************************************************/
    7568             : /*                            WriteVarInt()                             */
    7569             : /************************************************************************/
    7570             : 
    7571        5226 : inline void WriteVarInt(std::vector<GByte> &abyBuffer, int64_t nVal)
    7572             : {
    7573             :     uint64_t nUVal;
    7574        5226 :     if (nVal < 0)
    7575             :     {
    7576           7 :         if (nVal == std::numeric_limits<int64_t>::min())
    7577           0 :             nUVal = static_cast<uint64_t>(1) << 63;
    7578             :         else
    7579           7 :             nUVal = -nVal;
    7580           7 :         if (nUVal >= 0x40)
    7581             :         {
    7582           5 :             WriteUInt8(abyBuffer,
    7583           5 :                        static_cast<uint8_t>(0x80 | 0x40 | (nUVal & 0x3F)));
    7584           5 :             nUVal >>= 6;
    7585             :         }
    7586             :         else
    7587             :         {
    7588           2 :             WriteUInt8(abyBuffer, static_cast<uint8_t>(0x40 | (nUVal & 0x3F)));
    7589           2 :             return;
    7590             :         }
    7591             :     }
    7592             :     else
    7593             :     {
    7594        5219 :         nUVal = nVal;
    7595        5219 :         if (nUVal >= 0x40)
    7596             :         {
    7597        4170 :             WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nUVal & 0x3F)));
    7598        4170 :             nUVal >>= 6;
    7599             :         }
    7600             :         else
    7601             :         {
    7602        1049 :             WriteUInt8(abyBuffer, static_cast<uint8_t>((nUVal & 0x3F)));
    7603        1049 :             return;
    7604             :         }
    7605             :     }
    7606             : 
    7607        4175 :     WriteVarUInt(abyBuffer, nUVal);
    7608             : }
    7609             : 
    7610             : /************************************************************************/
    7611             : /*                            WriteFloat32()                            */
    7612             : /************************************************************************/
    7613             : 
    7614           2 : inline void WriteFloat32(std::vector<GByte> &abyBuffer, float fVal)
    7615             : {
    7616           2 :     CPL_LSBPTR32(&fVal);
    7617           2 :     const GByte *pabyInput = reinterpret_cast<const GByte *>(&fVal);
    7618           2 :     abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(fVal));
    7619           2 : }
    7620             : 
    7621             : /************************************************************************/
    7622             : /*                            WriteFloat64()                            */
    7623             : /************************************************************************/
    7624             : 
    7625           3 : inline void WriteFloat64(std::vector<GByte> &abyBuffer, double dfVal)
    7626             : {
    7627           3 :     CPL_LSBPTR64(&dfVal);
    7628           3 :     const GByte *pabyInput = reinterpret_cast<const GByte *>(&dfVal);
    7629           3 :     abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(dfVal));
    7630           3 : }
    7631             : 
    7632             : }  // namespace
    7633             : 
    7634             : /************************************************************************/
    7635             : /*                   OGRFeature::SerializeToBinary()                    */
    7636             : /************************************************************************/
    7637             : 
    7638             : /** Serialize the feature to a binary encoding.
    7639             :  *
    7640             :  * This saves the feature ID, attribute fields content and geometry fields
    7641             :  * content.
    7642             :  *
    7643             :  * This method is aimed at being paired with DeserializeFromBinary().
    7644             :  *
    7645             :  * The format of that encoding may vary across GDAL versions.
    7646             :  *
    7647             :  * Note that abyBuffer is cleared at the beginning of this function.
    7648             :  *
    7649             :  * @since 3.9
    7650             :  */
    7651        2609 : bool OGRFeature::SerializeToBinary(std::vector<GByte> &abyBuffer) const
    7652             : {
    7653        2609 :     const int nFieldCount = poDefn->GetFieldCount();
    7654        2609 :     const int nGeomFieldCount = poDefn->GetGeomFieldCount();
    7655             :     try
    7656             :     {
    7657        2609 :         abyBuffer.clear();
    7658             :         // Set field flags
    7659             :         // For attribute fields, we have 2 bits
    7660             :         // - first one set if the field is unset
    7661             :         // - second one set if the field is null
    7662             :         // For geometry fields, we have one bit set to indicate if the geometry
    7663             :         // is non-null.
    7664        2609 :         const size_t nPresenceFlagsSize =
    7665        2609 :             ((2 * nFieldCount + nGeomFieldCount) + 7) / 8;
    7666        2609 :         abyBuffer.resize(nPresenceFlagsSize);
    7667             : 
    7668        2609 :         WriteVarInt(abyBuffer, GetFID());
    7669             : 
    7670        1036 :         const auto SetFlagBit = [&abyBuffer](int iBit)
    7671        1036 :         { abyBuffer[iBit / 8] |= (1 << (iBit % 8)); };
    7672             : 
    7673        5249 :         for (int i = 0; i < nFieldCount; ++i)
    7674             :         {
    7675        2640 :             const OGRField &uField = pauFields[i];
    7676        2640 :             if (OGR_RawField_IsUnset(&uField))
    7677             :             {
    7678          23 :                 const int iBit = 2 * i;
    7679          23 :                 SetFlagBit(iBit);
    7680          23 :                 continue;
    7681             :             }
    7682        2617 :             if (OGR_RawField_IsNull(&uField))
    7683             :             {
    7684           1 :                 const int iBit = 2 * i + 1;
    7685           1 :                 SetFlagBit(iBit);
    7686           1 :                 continue;
    7687             :             }
    7688        2616 :             const auto poFDefn = poDefn->GetFieldDefn(i);
    7689        2616 :             switch (poFDefn->GetType())
    7690             :             {
    7691        2605 :                 case OFTInteger:
    7692             :                 {
    7693        2605 :                     WriteVarInt(abyBuffer, uField.Integer);
    7694        2605 :                     break;
    7695             :                 }
    7696           1 :                 case OFTInteger64:
    7697             :                 {
    7698           1 :                     WriteVarInt(abyBuffer, uField.Integer64);
    7699           1 :                     break;
    7700             :                 }
    7701           1 :                 case OFTReal:
    7702             :                 {
    7703           1 :                     WriteFloat64(abyBuffer, uField.Real);
    7704           1 :                     break;
    7705             :                 }
    7706           1 :                 case OFTString:
    7707             :                 {
    7708           1 :                     const size_t nStrSize = strlen(uField.String);
    7709           1 :                     WriteVarUInt(abyBuffer, nStrSize);
    7710           1 :                     const GByte *pabyStr =
    7711             :                         reinterpret_cast<const GByte *>(uField.String);
    7712           0 :                     abyBuffer.insert(abyBuffer.end(), pabyStr,
    7713           1 :                                      pabyStr + nStrSize);
    7714           1 :                     break;
    7715             :                 }
    7716           1 :                 case OFTIntegerList:
    7717             :                 {
    7718           1 :                     WriteVarInt(abyBuffer, uField.IntegerList.nCount);
    7719           3 :                     for (int j = 0; j < uField.IntegerList.nCount; ++j)
    7720           2 :                         WriteVarInt(abyBuffer, uField.IntegerList.paList[j]);
    7721           1 :                     break;
    7722             :                 }
    7723           1 :                 case OFTInteger64List:
    7724             :                 {
    7725           1 :                     WriteVarInt(abyBuffer, uField.Integer64List.nCount);
    7726           3 :                     for (int j = 0; j < uField.Integer64List.nCount; ++j)
    7727           2 :                         WriteVarInt(abyBuffer, uField.Integer64List.paList[j]);
    7728           1 :                     break;
    7729             :                 }
    7730           1 :                 case OFTRealList:
    7731             :                 {
    7732           1 :                     WriteVarInt(abyBuffer, uField.RealList.nCount);
    7733           3 :                     for (int j = 0; j < uField.RealList.nCount; ++j)
    7734           2 :                         WriteFloat64(abyBuffer, uField.RealList.paList[j]);
    7735           1 :                     break;
    7736             :                 }
    7737           1 :                 case OFTStringList:
    7738             :                 {
    7739           1 :                     WriteVarInt(abyBuffer, uField.StringList.nCount);
    7740           3 :                     for (int j = 0; j < uField.StringList.nCount; ++j)
    7741             :                     {
    7742           2 :                         const char *pszStr = uField.StringList.paList[j];
    7743           2 :                         const size_t nStrSize = strlen(pszStr);
    7744           2 :                         WriteVarUInt(abyBuffer, nStrSize);
    7745           2 :                         const GByte *pabyStr =
    7746             :                             reinterpret_cast<const GByte *>(pszStr);
    7747           0 :                         abyBuffer.insert(abyBuffer.end(), pabyStr,
    7748           2 :                                          pabyStr + nStrSize);
    7749             :                     }
    7750           1 :                     break;
    7751             :                 }
    7752           1 :                 case OFTBinary:
    7753             :                 {
    7754           1 :                     WriteVarInt(abyBuffer, uField.Binary.nCount);
    7755           0 :                     abyBuffer.insert(abyBuffer.end(), uField.Binary.paData,
    7756           1 :                                      uField.Binary.paData +
    7757           1 :                                          uField.Binary.nCount);
    7758           1 :                     break;
    7759             :                 }
    7760           0 :                 case OFTWideString:
    7761             :                 case OFTWideStringList:
    7762           0 :                     break;
    7763           1 :                 case OFTDate:
    7764             :                 {
    7765           1 :                     WriteVarInt(abyBuffer, uField.Date.Year);
    7766           1 :                     WriteUInt8(abyBuffer, uField.Date.Month);
    7767           1 :                     WriteUInt8(abyBuffer, uField.Date.Day);
    7768           1 :                     break;
    7769             :                 }
    7770           1 :                 case OFTTime:
    7771             :                 {
    7772           1 :                     WriteUInt8(abyBuffer, uField.Date.Hour);
    7773           1 :                     WriteUInt8(abyBuffer, uField.Date.Minute);
    7774           1 :                     WriteFloat32(abyBuffer, uField.Date.Second);
    7775           1 :                     WriteUInt8(abyBuffer, uField.Date.TZFlag);
    7776           1 :                     break;
    7777             :                 }
    7778           1 :                 case OFTDateTime:
    7779             :                 {
    7780           1 :                     WriteVarInt(abyBuffer, uField.Date.Year);
    7781           1 :                     WriteUInt8(abyBuffer, uField.Date.Month);
    7782           1 :                     WriteUInt8(abyBuffer, uField.Date.Day);
    7783           1 :                     WriteUInt8(abyBuffer, uField.Date.Hour);
    7784           1 :                     WriteUInt8(abyBuffer, uField.Date.Minute);
    7785           1 :                     WriteFloat32(abyBuffer, uField.Date.Second);
    7786           1 :                     WriteUInt8(abyBuffer, uField.Date.TZFlag);
    7787           1 :                     break;
    7788             :                 }
    7789             :             }
    7790             :         }
    7791        5216 :         for (int i = 0; i < nGeomFieldCount; ++i)
    7792             :         {
    7793        2607 :             if (!papoGeometries[i])
    7794             :             {
    7795        1012 :                 const int iBit = 2 * nFieldCount + i;
    7796        1012 :                 SetFlagBit(iBit);
    7797        1012 :                 continue;
    7798             :             }
    7799        1595 :             const size_t nSize = papoGeometries[i]->WkbSize();
    7800        1595 :             WriteVarUInt(abyBuffer, nSize);
    7801        1595 :             const size_t nBufSizeBefore = abyBuffer.size();
    7802        1595 :             abyBuffer.resize(nBufSizeBefore + nSize);
    7803        1595 :             papoGeometries[i]->exportToWkb(
    7804        1595 :                 wkbNDR, abyBuffer.data() + nBufSizeBefore, wkbVariantIso);
    7805             :         }
    7806        2609 :         return true;
    7807             :     }
    7808           0 :     catch (const std::bad_alloc &)
    7809             :     {
    7810           0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
    7811           0 :         return false;
    7812             :     }
    7813             : }
    7814             : 
    7815             : namespace
    7816             : {
    7817             : // Implementation borrowed to OpenFileGDB
    7818             : 
    7819             : /************************************************************************/
    7820             : /*                            ReadVarUInt()                             */
    7821             : /************************************************************************/
    7822             : 
    7823             : template <class OutType>
    7824        2197 : static bool ReadVarUInt(const GByte *&pabyIter, const GByte *pabyEnd,
    7825             :                         OutType &nOutVal)
    7826             : {
    7827        2197 :     if (pabyIter >= pabyEnd)
    7828           3 :         return false;
    7829        2194 :     OutType b = *pabyIter;
    7830        2194 :     if ((b & 0x80) == 0)
    7831             :     {
    7832        2189 :         pabyIter++;
    7833        2189 :         nOutVal = b;
    7834        2189 :         return true;
    7835             :     }
    7836           5 :     const GByte *pabyLocalIter = pabyIter + 1;
    7837           5 :     int nShift = 7;
    7838           5 :     OutType nVal = (b & 0x7F);
    7839             :     while (true)
    7840             :     {
    7841           5 :         if (pabyLocalIter >= pabyEnd)
    7842           0 :             return false;
    7843           5 :         b = *pabyLocalIter;
    7844           5 :         pabyLocalIter++;
    7845           5 :         nVal |= (b & 0x7F) << nShift;
    7846           5 :         if ((b & 0x80) == 0)
    7847             :         {
    7848           5 :             pabyIter = pabyLocalIter;
    7849           5 :             nOutVal = nVal;
    7850           5 :             return true;
    7851             :         }
    7852           0 :         nShift += 7;
    7853             :         // To avoid undefined behavior later when doing << nShift
    7854           0 :         if (nShift >= static_cast<int>(sizeof(OutType)) * 8)
    7855             :         {
    7856           0 :             return false;
    7857             :         }
    7858             :     }
    7859             : }
    7860             : 
    7861             : /************************************************************************/
    7862             : /*                             ReadVarInt()                             */
    7863             : /************************************************************************/
    7864             : 
    7865             : template <class OutType>
    7866             : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW static bool
    7867        7811 : ReadVarInt(const GByte *&pabyIter, const GByte *pabyEnd, OutType &nOutVal)
    7868             : {
    7869             :     GUInt32 b;
    7870             : 
    7871        7811 :     if (pabyIter >= pabyEnd)
    7872          15 :         return false;
    7873        7796 :     b = *pabyIter;
    7874        7796 :     GUIntBig nVal = (b & 0x3F);
    7875        7796 :     bool bNegative = (b & 0x40) != 0;
    7876        7796 :     if ((b & 0x80) == 0)
    7877             :     {
    7878        2545 :         pabyIter++;
    7879        2545 :         if (bNegative)
    7880           4 :             nOutVal = -static_cast<OutType>(nVal);
    7881             :         else
    7882        2541 :             nOutVal = static_cast<OutType>(nVal);
    7883        2545 :         return true;
    7884             :     }
    7885             : 
    7886        5251 :     const GByte *pabyLocalIter = pabyIter + 1;
    7887        5251 :     int nShift = 6;
    7888        2179 :     while (true)
    7889             :     {
    7890        7430 :         if (pabyLocalIter >= pabyEnd)
    7891          23 :             return false;
    7892        7407 :         GUIntBig b64 = *pabyLocalIter;
    7893        7407 :         pabyLocalIter++;
    7894        7407 :         nVal |= (b64 & 0x7F) << nShift;
    7895        7407 :         if ((b64 & 0x80) == 0)
    7896             :         {
    7897        5228 :             pabyIter = pabyLocalIter;
    7898        5228 :             if (bNegative)
    7899         813 :                 nOutVal = -static_cast<OutType>(nVal);
    7900             :             else
    7901        4415 :                 nOutVal = static_cast<OutType>(nVal);
    7902        5228 :             return true;
    7903             :         }
    7904        2179 :         nShift += 7;
    7905             :         // To avoid undefined behavior later when doing << nShift
    7906        2179 :         if (nShift >= static_cast<int>(sizeof(GIntBig)) * 8)
    7907             :         {
    7908           0 :             return false;
    7909             :         }
    7910             :     }
    7911             : }
    7912             : 
    7913             : /************************************************************************/
    7914             : /*                             ReadUInt8()                              */
    7915             : /************************************************************************/
    7916             : 
    7917        1207 : inline bool ReadUInt8(const GByte *&pabyIter, const GByte *pabyEnd, GByte &nVal)
    7918             : {
    7919        1207 :     if (pabyIter + sizeof(nVal) > pabyEnd)
    7920          10 :         return false;
    7921        1197 :     nVal = *pabyIter;
    7922        1197 :     pabyIter += sizeof(nVal);
    7923        1197 :     return true;
    7924             : }
    7925             : 
    7926             : /************************************************************************/
    7927             : /*                            ReadFloat32()                             */
    7928             : /************************************************************************/
    7929             : 
    7930         239 : inline bool ReadFloat32(const GByte *&pabyIter, const GByte *pabyEnd,
    7931             :                         float &fVal)
    7932             : {
    7933         239 :     if (pabyIter + sizeof(fVal) > pabyEnd)
    7934           8 :         return false;
    7935             :     // cppcheck-suppress bufferAccessOutOfBounds
    7936         231 :     memcpy(&fVal, pabyIter, sizeof(fVal));
    7937         231 :     CPL_LSBPTR32(&fVal);
    7938         231 :     pabyIter += sizeof(fVal);
    7939         231 :     return true;
    7940             : }
    7941             : 
    7942             : /************************************************************************/
    7943             : /*                            ReadFloat64()                             */
    7944             : /************************************************************************/
    7945             : 
    7946         541 : inline bool ReadFloat64(const GByte *&pabyIter, const GByte *pabyEnd,
    7947             :                         double &dfVal)
    7948             : {
    7949         541 :     if (pabyIter + sizeof(dfVal) > pabyEnd)
    7950          22 :         return false;
    7951         519 :     memcpy(&dfVal, pabyIter, sizeof(dfVal));
    7952         519 :     CPL_LSBPTR64(&dfVal);
    7953         519 :     pabyIter += sizeof(dfVal);
    7954         519 :     return true;
    7955             : }
    7956             : 
    7957             : }  // namespace
    7958             : 
    7959             : /************************************************************************/
    7960             : /*                 OGRFeature::DeserializeFromBinary()                  */
    7961             : /************************************************************************/
    7962             : 
    7963             : /** Instantiate a feature from a binary encoding produces by SerializeToBinary()
    7964             :  *
    7965             :  * This sets the feature ID, attribute fields content and geometry fields
    7966             :  * content.
    7967             :  *
    7968             :  * DeserializeFromBinary() should be called on a feature whose feature definition
    7969             :  * is exactly the same as the one on which SerializeToBinary() was called.
    7970             :  * (but there is no security issue if not doing that, or if feeding a "random"
    7971             :  * buffer to that method).
    7972             :  *
    7973             :  * The format of that encoding may vary across GDAL versions.
    7974             :  *
    7975             :  * @since 3.9
    7976             :  */
    7977        2861 : bool OGRFeature::DeserializeFromBinary(const GByte *pabyBuffer, size_t nSize)
    7978             : {
    7979        2861 :     Reset();
    7980             : 
    7981        2861 :     const GByte *const pabyFlags = pabyBuffer;
    7982        2861 :     const GByte *const pabyEnd = pabyBuffer + nSize;
    7983        2861 :     const int nFieldCount = poDefn->GetFieldCount();
    7984        2861 :     const int nGeomFieldCount = poDefn->GetGeomFieldCount();
    7985        2861 :     const size_t nPresenceFlagsSize =
    7986        2861 :         ((2 * nFieldCount + nGeomFieldCount) + 7) / 8;
    7987        2861 :     if (nSize < nPresenceFlagsSize)
    7988          12 :         return false;
    7989        2849 :     pabyBuffer += nPresenceFlagsSize;
    7990             : 
    7991        2849 :     if (!ReadVarInt(pabyBuffer, pabyEnd, nFID))
    7992          11 :         return false;
    7993             : 
    7994       12305 :     const auto IsFlagBitSet = [pabyFlags](int iBit) -> bool
    7995       12305 :     { return (pabyFlags[iBit / 8] & (1 << (iBit % 8))) != 0; };
    7996             : 
    7997        7530 :     for (int i = 0; i < nFieldCount; ++i)
    7998             :     {
    7999        4812 :         OGRField &uField = pauFields[i];
    8000             :         {
    8001        4812 :             const int iBit = 2 * i;
    8002        4812 :             if (IsFlagBitSet(iBit))
    8003             :             {
    8004             :                 // OGR_RawField_SetUnset(&uField);
    8005          35 :                 continue;
    8006             :             }
    8007             :         }
    8008             :         {
    8009        4777 :             const int iBit = 2 * i + 1;
    8010        4777 :             if (IsFlagBitSet(iBit))
    8011             :             {
    8012           1 :                 OGR_RawField_SetNull(&uField);
    8013           1 :                 continue;
    8014             :             }
    8015             :         }
    8016        4776 :         const auto poFDefn = poDefn->GetFieldDefn(i);
    8017        4776 :         switch (poFDefn->GetType())
    8018             :         {
    8019        2833 :             case OFTInteger:
    8020             :             {
    8021        2833 :                 uField.Set.nMarker2 = 0;
    8022        2833 :                 uField.Set.nMarker3 = 0;
    8023        2833 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Integer))
    8024           2 :                     return false;
    8025        2831 :                 break;
    8026             :             }
    8027         227 :             case OFTInteger64:
    8028             :             {
    8029         227 :                 uField.Set.nMarker2 = 0;
    8030         227 :                 uField.Set.nMarker3 = 0;
    8031         227 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Integer64))
    8032           7 :                     return false;
    8033         220 :                 break;
    8034             :             }
    8035         220 :             case OFTReal:
    8036             :             {
    8037         220 :                 uField.Set.nMarker2 = 0;
    8038         220 :                 uField.Set.nMarker3 = 0;
    8039         220 :                 if (!ReadFloat64(pabyBuffer, pabyEnd, uField.Real))
    8040           8 :                     return false;
    8041         212 :                 break;
    8042             :             }
    8043         212 :             case OFTString:
    8044             :             {
    8045         212 :                 size_t nStrSize = 0;
    8046         423 :                 if (!ReadVarUInt(pabyBuffer, pabyEnd, nStrSize) ||
    8047         211 :                     nStrSize > std::numeric_limits<size_t>::max() - 1)
    8048             :                 {
    8049           9 :                     return false;
    8050             :                 }
    8051         211 :                 if (nStrSize > static_cast<size_t>(pabyEnd - pabyBuffer))
    8052           8 :                     return false;
    8053             :                 auto ptr =
    8054         203 :                     static_cast<char *>(VSI_MALLOC_VERBOSE(nStrSize + 1));
    8055         203 :                 if (!ptr)
    8056           0 :                     return false;
    8057         203 :                 uField.Set.nMarker2 = 0;
    8058         203 :                 uField.Set.nMarker3 = 0;
    8059         203 :                 uField.String = ptr;
    8060         203 :                 memcpy(uField.String, pabyBuffer, nStrSize);
    8061         203 :                 uField.String[nStrSize] = 0;
    8062         203 :                 pabyBuffer += nStrSize;
    8063         203 :                 break;
    8064             :             }
    8065         196 :             case OFTIntegerList:
    8066             :             {
    8067         196 :                 int nCount = 0;
    8068         388 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
    8069         192 :                     nCount > pabyEnd - pabyBuffer)
    8070             :                 {
    8071          11 :                     return false;
    8072             :                 }
    8073             :                 auto ptr = static_cast<int *>(
    8074         190 :                     VSI_MALLOC2_VERBOSE(nCount, sizeof(int)));
    8075         190 :                 if (!ptr)
    8076           3 :                     return false;
    8077         187 :                 uField.Set.nMarker2 = 0;
    8078         187 :                 uField.Set.nMarker3 = 0;
    8079         187 :                 uField.IntegerList.paList = ptr;
    8080         187 :                 uField.IntegerList.nCount = nCount;
    8081         559 :                 for (int j = 0; j < nCount; ++j)
    8082             :                 {
    8083         374 :                     if (!ReadVarInt(pabyBuffer, pabyEnd,
    8084         374 :                                     uField.IntegerList.paList[j]))
    8085           2 :                         return false;
    8086             :                 }
    8087         185 :                 break;
    8088             :             }
    8089         185 :             case OFTInteger64List:
    8090             :             {
    8091         185 :                 int nCount = 0;
    8092         368 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
    8093         183 :                     nCount > pabyEnd - pabyBuffer)
    8094             :                 {
    8095          11 :                     return false;
    8096             :                 }
    8097             :                 auto ptr = static_cast<GIntBig *>(
    8098         180 :                     VSI_MALLOC2_VERBOSE(nCount, sizeof(GIntBig)));
    8099         180 :                 if (!ptr)
    8100           0 :                     return false;
    8101         180 :                 uField.Set.nMarker2 = 0;
    8102         180 :                 uField.Set.nMarker3 = 0;
    8103         180 :                 uField.Integer64List.paList = ptr;
    8104         180 :                 uField.Integer64List.nCount = nCount;
    8105         545 :                 for (int j = 0; j < nCount; ++j)
    8106             :                 {
    8107         371 :                     if (!ReadVarInt(pabyBuffer, pabyEnd,
    8108         371 :                                     uField.Integer64List.paList[j]))
    8109           6 :                         return false;
    8110             :                 }
    8111         174 :                 break;
    8112             :             }
    8113         174 :             case OFTRealList:
    8114             :             {
    8115         174 :                 int nCount = 0;
    8116         343 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
    8117         169 :                     nCount > pabyEnd - pabyBuffer)
    8118             :                 {
    8119          26 :                     return false;
    8120             :                 }
    8121             :                 auto ptr = static_cast<double *>(
    8122         165 :                     VSI_MALLOC2_VERBOSE(nCount, sizeof(double)));
    8123         165 :                 if (!ptr)
    8124           3 :                     return false;
    8125         162 :                 uField.Set.nMarker2 = 0;
    8126         162 :                 uField.Set.nMarker3 = 0;
    8127         162 :                 uField.RealList.paList = ptr;
    8128         162 :                 uField.RealList.nCount = nCount;
    8129         469 :                 for (int j = 0; j < nCount; ++j)
    8130             :                 {
    8131         321 :                     if (!ReadFloat64(pabyBuffer, pabyEnd,
    8132         321 :                                      uField.RealList.paList[j]))
    8133          14 :                         return false;
    8134             :                 }
    8135         148 :                 break;
    8136             :             }
    8137         148 :             case OFTStringList:
    8138             :             {
    8139         148 :                 int nCount = 0;
    8140         295 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
    8141         441 :                     nCount > std::numeric_limits<int>::max() - 1 ||
    8142         146 :                     nCount > pabyEnd - pabyBuffer)
    8143             :                 {
    8144          17 :                     return false;
    8145             :                 }
    8146             :                 auto ptr = static_cast<char **>(
    8147         143 :                     VSI_CALLOC_VERBOSE(nCount + 1, sizeof(char *)));
    8148         143 :                 if (!ptr)
    8149           0 :                     return false;
    8150         143 :                 uField.Set.nMarker2 = 0;
    8151         143 :                 uField.Set.nMarker3 = 0;
    8152         143 :                 uField.StringList.paList = ptr;
    8153         143 :                 uField.StringList.nCount = nCount;
    8154         413 :                 for (int j = 0; j < nCount; ++j)
    8155             :                 {
    8156         282 :                     size_t nStrSize = 0;
    8157         563 :                     if (!ReadVarUInt(pabyBuffer, pabyEnd, nStrSize) ||
    8158         281 :                         nStrSize > std::numeric_limits<size_t>::max() - 1)
    8159             :                     {
    8160          12 :                         return false;
    8161             :                     }
    8162         281 :                     if (nStrSize > static_cast<size_t>(pabyEnd - pabyBuffer))
    8163          11 :                         return false;
    8164         540 :                     uField.StringList.paList[j] =
    8165         270 :                         static_cast<char *>(VSI_MALLOC_VERBOSE(nStrSize + 1));
    8166         270 :                     if (!uField.StringList.paList[j])
    8167           0 :                         return false;
    8168         270 :                     memcpy(uField.StringList.paList[j], pabyBuffer, nStrSize);
    8169         270 :                     uField.StringList.paList[j][nStrSize] = 0;
    8170         270 :                     pabyBuffer += nStrSize;
    8171             :                 }
    8172         131 :                 break;
    8173             :             }
    8174         203 :             case OFTBinary:
    8175             :             {
    8176         203 :                 int nBinSize = 0;
    8177         203 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, nBinSize) || nBinSize < 0)
    8178             :                 {
    8179           7 :                     return false;
    8180             :                 }
    8181         199 :                 if (nBinSize > pabyEnd - pabyBuffer)
    8182           3 :                     return false;
    8183         196 :                 auto ptr = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nBinSize));
    8184         196 :                 if (!ptr)
    8185           0 :                     return false;
    8186         196 :                 uField.Set.nMarker2 = 0;
    8187         196 :                 uField.Set.nMarker3 = 0;
    8188         196 :                 uField.Binary.paData = ptr;
    8189         196 :                 uField.Binary.nCount = nBinSize;
    8190         196 :                 memcpy(uField.Binary.paData, pabyBuffer, nBinSize);
    8191         196 :                 pabyBuffer += nBinSize;
    8192         196 :                 break;
    8193             :             }
    8194           0 :             case OFTWideString:
    8195             :             case OFTWideStringList:
    8196           0 :                 break;
    8197         131 :             case OFTDate:
    8198             :             {
    8199         131 :                 memset(&uField, 0, sizeof(uField));
    8200         131 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Date.Year) ||
    8201         259 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Month) ||
    8202         128 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Day))
    8203             :                 {
    8204           4 :                     return false;
    8205             :                 }
    8206         127 :                 break;
    8207             :             }
    8208         127 :             case OFTTime:
    8209             :             {
    8210         127 :                 memset(&uField, 0, sizeof(uField));
    8211         127 :                 if (!ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Hour) ||
    8212         126 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Minute) ||
    8213         374 :                     !ReadFloat32(pabyBuffer, pabyEnd, uField.Date.Second) ||
    8214         121 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.TZFlag))
    8215             :                 {
    8216           7 :                     return false;
    8217             :                 }
    8218         120 :                 break;
    8219             :             }
    8220         120 :             case OFTDateTime:
    8221             :             {
    8222         120 :                 memset(&uField, 0, sizeof(uField));
    8223         120 :                 if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Date.Year) ||
    8224         118 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Month) ||
    8225         117 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Day) ||
    8226         116 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Hour) ||
    8227         115 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Minute) ||
    8228         348 :                     !ReadFloat32(pabyBuffer, pabyEnd, uField.Date.Second) ||
    8229         110 :                     !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.TZFlag))
    8230             :                 {
    8231          11 :                     return false;
    8232             :                 }
    8233         109 :                 break;
    8234             :             }
    8235             :         }
    8236             :     }
    8237        5402 :     for (int i = 0; i < nGeomFieldCount; ++i)
    8238             :     {
    8239        2716 :         const int iBit = 2 * nFieldCount + i;
    8240        2716 :         if (IsFlagBitSet(iBit))
    8241             :         {
    8242        1013 :             continue;
    8243             :         }
    8244        1703 :         size_t nWkbSize = 0;
    8245        1703 :         if (!ReadVarUInt(pabyBuffer, pabyEnd, nWkbSize))
    8246             :         {
    8247          32 :             return false;
    8248             :         }
    8249        1702 :         if (nWkbSize > static_cast<size_t>(pabyEnd - pabyBuffer))
    8250             :         {
    8251          23 :             return false;
    8252             :         }
    8253        1679 :         OGRGeometry *poGeom = nullptr;
    8254        1679 :         if (OGRGeometryFactory::createFromWkb(
    8255        1679 :                 pabyBuffer, poDefn->GetGeomFieldDefn(i)->GetSpatialRef(),
    8256        3350 :                 &poGeom, nWkbSize, wkbVariantIso) != OGRERR_NONE ||
    8257        1671 :             !poGeom)
    8258             :         {
    8259           8 :             delete poGeom;
    8260           8 :             return false;
    8261             :         }
    8262        1671 :         pabyBuffer += nWkbSize;
    8263        1671 :         papoGeometries[i] = poGeom;
    8264             :     }
    8265        2686 :     return true;
    8266             : }
    8267             : 
    8268             : /************************************************************************/
    8269             : /*                    OGRFeature::ConstFieldIterator                    */
    8270             : /************************************************************************/
    8271             : 
    8272             : struct OGRFeature::FieldValue::Private
    8273             : {
    8274             :     CPL_DISALLOW_COPY_ASSIGN(Private)
    8275             : 
    8276             :     OGRFeature *m_poSelf = nullptr;
    8277             :     int m_nPos = 0;
    8278             :     mutable std::vector<int> m_anList{};
    8279             :     mutable std::vector<GIntBig> m_anList64{};
    8280             :     mutable std::vector<double> m_adfList{};
    8281             :     mutable std::vector<std::string> m_aosList{};
    8282             : 
    8283           4 :     Private(const OGRFeature *poSelf, int iFieldIndex)
    8284           4 :         : m_poSelf(const_cast<OGRFeature *>(poSelf)), m_nPos(iFieldIndex)
    8285             :     {
    8286           4 :     }
    8287             : 
    8288          47 :     Private(OGRFeature *poSelf, int iFieldIndex)
    8289          47 :         : m_poSelf(poSelf), m_nPos(iFieldIndex)
    8290             :     {
    8291          47 :     }
    8292             : };
    8293             : 
    8294             : struct OGRFeature::ConstFieldIterator::Private
    8295             : {
    8296             :     CPL_DISALLOW_COPY_ASSIGN(Private)
    8297             : 
    8298             :     OGRFeature::FieldValue m_oValue;
    8299             :     int m_nPos = 0;
    8300             : 
    8301           4 :     Private(const OGRFeature *poSelf, int iFieldIndex)
    8302           4 :         : m_oValue(poSelf, iFieldIndex)
    8303             :     {
    8304           4 :     }
    8305             : };
    8306             : 
    8307             : //! @cond Doxygen_Suppress
    8308           4 : OGRFeature::ConstFieldIterator::ConstFieldIterator(const OGRFeature *poSelf,
    8309           4 :                                                    int nPos)
    8310           4 :     : m_poPrivate(new Private(poSelf, nPos))
    8311             : {
    8312           4 :     m_poPrivate->m_nPos = nPos;
    8313           4 : }
    8314             : 
    8315             : OGRFeature::ConstFieldIterator::~ConstFieldIterator() = default;
    8316             : 
    8317          22 : const OGRFeature::FieldValue &OGRFeature::ConstFieldIterator::operator*() const
    8318             : {
    8319          22 :     return m_poPrivate->m_oValue;
    8320             : }
    8321             : 
    8322          22 : OGRFeature::ConstFieldIterator &OGRFeature::ConstFieldIterator::operator++()
    8323             : {
    8324          22 :     ++m_poPrivate->m_nPos;
    8325          22 :     m_poPrivate->m_oValue.m_poPrivate->m_nPos = m_poPrivate->m_nPos;
    8326          22 :     return *this;
    8327             : }
    8328             : 
    8329          24 : bool OGRFeature::ConstFieldIterator::operator!=(
    8330             :     const ConstFieldIterator &it) const
    8331             : {
    8332          24 :     return m_poPrivate->m_nPos != it.m_poPrivate->m_nPos;
    8333             : }
    8334             : 
    8335             : //! @endcond
    8336             : 
    8337           2 : OGRFeature::ConstFieldIterator OGRFeature::begin() const
    8338             : {
    8339           2 :     return {this, 0};
    8340             : }
    8341             : 
    8342           2 : OGRFeature::ConstFieldIterator OGRFeature::end() const
    8343             : {
    8344           2 :     return {this, GetFieldCount()};
    8345             : }
    8346             : 
    8347             : /************************************************************************/
    8348             : /*                        OGRFeature::FieldValue                        */
    8349             : /************************************************************************/
    8350             : 
    8351           4 : OGRFeature::FieldValue::FieldValue(const OGRFeature *poFeature, int iFieldIndex)
    8352           4 :     : m_poPrivate(new Private(poFeature, iFieldIndex))
    8353             : {
    8354           4 : }
    8355             : 
    8356          47 : OGRFeature::FieldValue::FieldValue(OGRFeature *poFeature, int iFieldIndex)
    8357          47 :     : m_poPrivate(new Private(poFeature, iFieldIndex))
    8358             : {
    8359          47 : }
    8360             : 
    8361          14 : OGRFeature::FieldValue &OGRFeature::FieldValue::Assign(const FieldValue &oOther)
    8362             : {
    8363          27 :     if (&oOther != this &&
    8364          13 :         !(m_poPrivate->m_poSelf == oOther.m_poPrivate->m_poSelf &&
    8365           2 :           m_poPrivate->m_nPos == oOther.m_poPrivate->m_nPos))
    8366             :     {
    8367          12 :         OGRFieldType eOtherType(oOther.GetType());
    8368          12 :         if (oOther.IsNull())
    8369           1 :             SetNull();
    8370          11 :         else if (oOther.IsUnset())
    8371           1 :             Unset();
    8372          10 :         else if (eOtherType == OFTInteger)
    8373           2 :             m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8374             :                                             oOther.GetInteger());
    8375           8 :         else if (eOtherType == OFTInteger64)
    8376           1 :             m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8377             :                                             oOther.GetInteger64());
    8378           7 :         else if (eOtherType == OFTReal)
    8379           1 :             m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8380             :                                             oOther.GetDouble());
    8381           6 :         else if (eOtherType == OFTString)
    8382           1 :             m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8383             :                                             oOther.GetString());
    8384           5 :         else if (eOtherType == OFTDate || eOtherType == OFTDateTime ||
    8385             :                  eOtherType == OFTTime)
    8386             :         {
    8387           1 :             int nYear = 0;
    8388           1 :             int nMonth = 0;
    8389           1 :             int nDay = 0;
    8390           1 :             int nHour = 0;
    8391           1 :             int nMinute = 0;
    8392           1 :             float fSecond = 0.0f;
    8393           1 :             int nTZFlag = 0;
    8394           1 :             oOther.GetDateTime(&nYear, &nMonth, &nDay, &nHour, &nMinute,
    8395             :                                &fSecond, &nTZFlag);
    8396           1 :             m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nYear, nMonth,
    8397             :                                             nDay, nHour, nMinute, fSecond,
    8398           1 :                                             nTZFlag);
    8399             :         }
    8400           4 :         else if (eOtherType == OFTStringList)
    8401             :         {
    8402           2 :             m_poPrivate->m_poSelf->SetField(
    8403           1 :                 m_poPrivate->m_nPos,
    8404           2 :                 oOther.m_poPrivate->m_poSelf->GetFieldAsStringList(
    8405           1 :                     oOther.m_poPrivate->m_nPos));
    8406             :         }
    8407           3 :         else if (eOtherType == OFTIntegerList)
    8408             :         {
    8409           1 :             operator=(oOther.GetAsIntegerList());
    8410             :         }
    8411           2 :         else if (eOtherType == OFTInteger64List)
    8412             :         {
    8413           1 :             operator=(oOther.GetAsInteger64List());
    8414             :         }
    8415           1 :         else if (eOtherType == OFTRealList)
    8416             :         {
    8417           1 :             operator=(oOther.GetAsDoubleList());
    8418             :         }
    8419             :     }
    8420          14 :     return *this;
    8421             : }
    8422             : 
    8423             : OGRFeature::FieldValue &
    8424          12 : OGRFeature::FieldValue::operator=(const FieldValue &oOther)
    8425             : {
    8426          12 :     return Assign(oOther);
    8427             : }
    8428             : 
    8429             : //! @cond Doxygen_Suppress
    8430           2 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(FieldValue &&oOther)
    8431             : {
    8432           2 :     return Assign(oOther);
    8433             : }
    8434             : 
    8435             : //! @endcond
    8436             : 
    8437           1 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(int nVal)
    8438             : {
    8439           1 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nVal);
    8440           1 :     return *this;
    8441             : }
    8442             : 
    8443           1 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(GIntBig nVal)
    8444             : {
    8445           1 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nVal);
    8446           1 :     return *this;
    8447             : }
    8448             : 
    8449           1 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(double dfVal)
    8450             : {
    8451           1 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, dfVal);
    8452           1 :     return *this;
    8453             : }
    8454             : 
    8455           2 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(const char *pszVal)
    8456             : {
    8457           2 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, pszVal);
    8458           2 :     return *this;
    8459             : }
    8460             : 
    8461             : OGRFeature::FieldValue &
    8462           1 : OGRFeature::FieldValue::operator=(const std::string &osVal)
    8463             : {
    8464           1 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, osVal.c_str());
    8465           1 :     return *this;
    8466             : }
    8467             : 
    8468             : OGRFeature::FieldValue &
    8469           3 : OGRFeature::FieldValue::operator=(const std::vector<int> &oArray)
    8470             : {
    8471           9 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8472           3 :                                     static_cast<int>(oArray.size()),
    8473           5 :                                     oArray.empty() ? nullptr : oArray.data());
    8474           3 :     return *this;
    8475             : }
    8476             : 
    8477             : OGRFeature::FieldValue &
    8478           3 : OGRFeature::FieldValue::operator=(const std::vector<GIntBig> &oArray)
    8479             : {
    8480           9 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8481           3 :                                     static_cast<int>(oArray.size()),
    8482           5 :                                     oArray.empty() ? nullptr : oArray.data());
    8483           3 :     return *this;
    8484             : }
    8485             : 
    8486             : OGRFeature::FieldValue &
    8487           3 : OGRFeature::FieldValue::operator=(const std::vector<double> &oArray)
    8488             : {
    8489           9 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
    8490           3 :                                     static_cast<int>(oArray.size()),
    8491           5 :                                     oArray.empty() ? nullptr : oArray.data());
    8492           3 :     return *this;
    8493             : }
    8494             : 
    8495             : OGRFeature::FieldValue &
    8496           2 : OGRFeature::FieldValue::operator=(const std::vector<std::string> &oArray)
    8497             : {
    8498           2 :     CPLStringList aosList;
    8499           4 :     for (auto &&oStr : oArray)
    8500           2 :         aosList.AddString(oStr.c_str());
    8501           2 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, aosList.List());
    8502           4 :     return *this;
    8503             : }
    8504             : 
    8505             : OGRFeature::FieldValue &
    8506           2 : OGRFeature::FieldValue::operator=(CSLConstList papszValues)
    8507             : {
    8508           2 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, papszValues);
    8509           2 :     return *this;
    8510             : }
    8511             : 
    8512           1 : void OGRFeature::FieldValue::SetDateTime(int nYear, int nMonth, int nDay,
    8513             :                                          int nHour, int nMinute, float fSecond,
    8514             :                                          int nTZFlag)
    8515             : {
    8516           1 :     m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nYear, nMonth, nDay,
    8517             :                                     nHour, nMinute, fSecond, nTZFlag);
    8518           1 : }
    8519             : 
    8520           2 : void OGRFeature::FieldValue::SetNull()
    8521             : {
    8522           2 :     m_poPrivate->m_poSelf->SetFieldNull(m_poPrivate->m_nPos);
    8523           2 : }
    8524             : 
    8525           3 : void OGRFeature::FieldValue::clear()
    8526             : {
    8527           3 :     m_poPrivate->m_poSelf->UnsetField(m_poPrivate->m_nPos);
    8528           3 : }
    8529             : 
    8530             : //! @cond Doxygen_Suppress
    8531             : OGRFeature::FieldValue::~FieldValue() = default;
    8532             : 
    8533             : //! @endcond
    8534             : 
    8535         188 : int OGRFeature::FieldValue::GetIndex() const
    8536             : {
    8537         188 :     return m_poPrivate->m_nPos;
    8538             : }
    8539             : 
    8540          89 : const OGRFieldDefn *OGRFeature::FieldValue::GetDefn() const
    8541             : {
    8542          89 :     return m_poPrivate->m_poSelf->GetFieldDefnRef(GetIndex());
    8543             : }
    8544             : 
    8545          48 : const OGRField *OGRFeature::FieldValue::GetRawValue() const
    8546             : {
    8547          48 :     return &(m_poPrivate->m_poSelf->pauFields[GetIndex()]);
    8548             : }
    8549             : 
    8550          15 : bool OGRFeature::FieldValue::IsUnset() const
    8551             : {
    8552          15 :     return CPL_TO_BOOL(OGR_RawField_IsUnset(GetRawValue()));
    8553             : }
    8554             : 
    8555          15 : bool OGRFeature::FieldValue::IsNull() const
    8556             : {
    8557          15 :     return CPL_TO_BOOL(OGR_RawField_IsNull(GetRawValue()));
    8558             : }
    8559             : 
    8560           5 : int OGRFeature::FieldValue::GetAsInteger() const
    8561             : {
    8562           5 :     return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8563           5 :         ->GetFieldAsInteger(GetIndex());
    8564             : }
    8565             : 
    8566           4 : GIntBig OGRFeature::FieldValue::GetAsInteger64() const
    8567             : {
    8568           4 :     return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8569           4 :         ->GetFieldAsInteger64(GetIndex());
    8570             : }
    8571             : 
    8572           4 : double OGRFeature::FieldValue::GetAsDouble() const
    8573             : {
    8574           4 :     return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8575           4 :         ->GetFieldAsDouble(GetIndex());
    8576             : }
    8577             : 
    8578           5 : const char *OGRFeature::FieldValue::GetAsString() const
    8579             : {
    8580           5 :     return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8581           5 :         ->GetFieldAsString(GetIndex());
    8582             : }
    8583             : 
    8584           2 : bool OGRFeature::FieldValue::GetDateTime(int *pnYear, int *pnMonth, int *pnDay,
    8585             :                                          int *pnHour, int *pnMinute,
    8586             :                                          float *pfSecond, int *pnTZFlag) const
    8587             : {
    8588           2 :     return CPL_TO_BOOL(const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8589             :                            ->GetFieldAsDateTime(GetIndex(), pnYear, pnMonth,
    8590             :                                                 pnDay, pnHour, pnMinute,
    8591           2 :                                                 pfSecond, pnTZFlag));
    8592             : }
    8593             : 
    8594           2 : const std::vector<int> &OGRFeature::FieldValue::GetAsIntegerList() const
    8595             : {
    8596           2 :     int nCount = 0;
    8597           2 :     auto &&panList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8598           2 :                          ->GetFieldAsIntegerList(GetIndex(), &nCount);
    8599           2 :     m_poPrivate->m_anList.assign(panList, panList + nCount);
    8600           2 :     return m_poPrivate->m_anList;
    8601             : }
    8602             : 
    8603           2 : const std::vector<GIntBig> &OGRFeature::FieldValue::GetAsInteger64List() const
    8604             : {
    8605           2 :     int nCount = 0;
    8606           2 :     auto &&panList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8607           2 :                          ->GetFieldAsInteger64List(GetIndex(), &nCount);
    8608           2 :     m_poPrivate->m_anList64.assign(panList, panList + nCount);
    8609           2 :     return m_poPrivate->m_anList64;
    8610             : }
    8611             : 
    8612           2 : const std::vector<double> &OGRFeature::FieldValue::GetAsDoubleList() const
    8613             : {
    8614           2 :     int nCount = 0;
    8615           2 :     auto &&panList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8616           2 :                          ->GetFieldAsDoubleList(GetIndex(), &nCount);
    8617           2 :     m_poPrivate->m_adfList.assign(panList, panList + nCount);
    8618           2 :     return m_poPrivate->m_adfList;
    8619             : }
    8620             : 
    8621           1 : const std::vector<std::string> &OGRFeature::FieldValue::GetAsStringList() const
    8622             : {
    8623           1 :     auto &&papszList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8624           1 :                            ->GetFieldAsStringList(GetIndex());
    8625           1 :     m_poPrivate->m_aosList.clear();
    8626           1 :     if (papszList)
    8627             :     {
    8628           3 :         for (char **papszIter = papszList; *papszIter; ++papszIter)
    8629             :         {
    8630           2 :             m_poPrivate->m_aosList.emplace_back(*papszIter);
    8631             :         }
    8632             :     }
    8633           1 :     return m_poPrivate->m_aosList;
    8634             : }
    8635             : 
    8636           2 : OGRFeature::FieldValue::operator CSLConstList() const
    8637             : {
    8638             :     return const_cast<CSLConstList>(
    8639           2 :         const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
    8640           2 :             ->GetFieldAsStringList(GetIndex()));
    8641             : }
    8642             : 
    8643          16 : OGRRangeFieldDomain *OGRRangeFieldDomain::Clone() const
    8644             : {
    8645             :     auto poDomain = new OGRRangeFieldDomain(
    8646          16 :         m_osName, m_osDescription, m_eFieldType, m_eFieldSubType, m_sMin,
    8647          16 :         m_bMinIsInclusive, m_sMax, m_bMaxIsInclusive);
    8648          16 :     poDomain->SetMergePolicy(m_eMergePolicy);
    8649          16 :     poDomain->SetSplitPolicy(m_eSplitPolicy);
    8650          16 :     return poDomain;
    8651             : }
    8652             : 
    8653          15 : OGRGlobFieldDomain *OGRGlobFieldDomain::Clone() const
    8654             : {
    8655             :     auto poDomain = new OGRGlobFieldDomain(
    8656          15 :         m_osName, m_osDescription, m_eFieldType, m_eFieldSubType, m_osGlob);
    8657          15 :     poDomain->SetMergePolicy(m_eMergePolicy);
    8658          15 :     poDomain->SetSplitPolicy(m_eSplitPolicy);
    8659          15 :     return poDomain;
    8660             : }
    8661             : #if defined(__GNUC__)
    8662             : #pragma GCC diagnostic pop
    8663             : #endif

Generated by: LCOV version 1.14