Coverage Report

Created: 2026-04-01 06:20

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