Coverage Report

Created: 2025-11-16 06:25

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