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

Generated by: LCOV version 1.14