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

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

Generated by: LCOV version 1.14