Coverage Report

Created: 2025-06-13 06:29

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