Coverage Report

Created: 2026-04-01 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrfeaturedefn.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  The OGRFeatureDefn class implementation.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 1999,  Les Technologies SoftMap Inc.
9
 * Copyright (c) 2009-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_feature.h"
16
17
#include <algorithm>
18
#include <cassert>
19
#include <cstring>
20
21
#include "cpl_conv.h"
22
#include "cpl_error.h"
23
#include "cpl_string.h"
24
#include "ogr_api.h"
25
#include "ogr_core.h"
26
#include "ogr_p.h"
27
#include "ograpispy.h"
28
29
/************************************************************************/
30
/*                           OGRFeatureDefn()                           */
31
/************************************************************************/
32
33
/**
34
 * \brief Constructor.
35
 *
36
 * The OGRFeatureDefn maintains a reference count, but this starts at
37
 * zero.  It is mainly intended to represent a count of OGRFeature's
38
 * based on this definition.
39
 *
40
 * This method is the same as the C function OGR_FD_Create().
41
 *
42
 * @param pszName the name to be assigned to this layer/class.  It does not
43
 * need to be unique.
44
 */
45
46
OGRFeatureDefn::OGRFeatureDefn(const char *pszName)
47
0
{
48
0
    pszFeatureClassName = CPLStrdup(pszName);
49
0
    apoGeomFieldDefn.emplace_back(
50
0
        std::make_unique<OGRGeomFieldDefn>("", wkbUnknown));
51
0
}
52
53
/************************************************************************/
54
/*                           OGR_FD_Create()                            */
55
/************************************************************************/
56
/**
57
 * \brief Create a new feature definition object to hold the field definitions.
58
 *
59
 * The OGRFeatureDefn maintains a reference count, but this starts at
60
 * zero, and should normally be incremented by the owner.
61
 *
62
 * This function is the same as the C++ method
63
 * OGRFeatureDefn::OGRFeatureDefn().
64
 *
65
 * @param pszName the name to be assigned to this layer/class.  It does not
66
 * need to be unique.
67
 * @return handle to the newly created feature definition.
68
 */
69
70
OGRFeatureDefnH OGR_FD_Create(const char *pszName)
71
72
0
{
73
0
    return OGRFeatureDefn::ToHandle(new OGRFeatureDefn(pszName));
74
0
}
75
76
/************************************************************************/
77
/*                          ~OGRFeatureDefn()                           */
78
/************************************************************************/
79
80
OGRFeatureDefn::~OGRFeatureDefn()
81
82
0
{
83
0
    if (nRefCount != 0)
84
0
    {
85
0
        CPLDebug("OGRFeatureDefn",
86
0
                 "OGRFeatureDefn %s with a ref count of %d deleted!",
87
0
                 pszFeatureClassName, nRefCount);
88
0
    }
89
90
0
    CPLFree(pszFeatureClassName);
91
0
}
92
93
/************************************************************************/
94
/*                           OGR_FD_Destroy()                           */
95
/************************************************************************/
96
/**
97
 * \brief Destroy a feature definition object and release all memory associated
98
 * with it.
99
 *
100
 * This function is the same as the C++ method
101
 * OGRFeatureDefn::~OGRFeatureDefn().
102
 *
103
 * @param hDefn handle to the feature definition to be destroyed.
104
 */
105
106
void OGR_FD_Destroy(OGRFeatureDefnH hDefn)
107
108
0
{
109
0
    delete OGRFeatureDefn::FromHandle(hDefn);
110
0
}
111
112
/************************************************************************/
113
/*                              Release()                               */
114
/************************************************************************/
115
116
/**
117
 * \fn void OGRFeatureDefn::Release();
118
 *
119
 * \brief Drop a reference to this object, and destroy if no longer referenced.
120
 */
121
122
void OGRFeatureDefn::Release()
123
124
0
{
125
0
#ifdef __GNUC__
126
0
#pragma GCC diagnostic push
127
0
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
128
0
#endif
129
0
    if (Dereference() <= 0)
130
0
        delete this;
131
0
#ifdef __GNUC__
132
0
#pragma GCC diagnostic pop
133
0
#endif
134
0
}
135
136
/************************************************************************/
137
/*                           OGR_FD_Release()                           */
138
/************************************************************************/
139
140
/**
141
 * \brief Drop a reference, and destroy if unreferenced.
142
 *
143
 * This function is the same as the C++ method OGRFeatureDefn::Release().
144
 *
145
 * @param hDefn handle to the feature definition to be released.
146
 */
147
148
void OGR_FD_Release(OGRFeatureDefnH hDefn)
149
150
0
{
151
0
    OGRFeatureDefn::FromHandle(hDefn)->Release();
152
0
}
153
154
/************************************************************************/
155
/*                               Clone()                                */
156
/************************************************************************/
157
158
/**
159
 * \fn OGRFeatureDefn *OGRFeatureDefn::Clone() const;
160
 *
161
 * \brief Create a copy of this feature definition.
162
 *
163
 * Creates a deep copy of the feature definition.
164
 * The reference counter of the copy is initialized at 0.
165
 *
166
 * @return the copy.
167
 */
168
169
OGRFeatureDefn *OGRFeatureDefn::Clone() const
170
171
0
{
172
0
    OGRFeatureDefn *poCopy = new OGRFeatureDefn(GetName());
173
174
0
    {
175
0
        const int nFieldCount = GetFieldCount();
176
0
        poCopy->apoFieldDefn.reserve(nFieldCount);
177
0
        for (int i = 0; i < nFieldCount; i++)
178
0
            poCopy->AddFieldDefn(GetFieldDefn(i));
179
0
    }
180
181
0
    {
182
        // Remove the default geometry field created instantiation.
183
0
        poCopy->DeleteGeomFieldDefn(0);
184
0
        const int nGeomFieldCount = GetGeomFieldCount();
185
0
        poCopy->apoGeomFieldDefn.reserve(nGeomFieldCount);
186
0
        for (int i = 0; i < nGeomFieldCount; i++)
187
0
            poCopy->AddGeomFieldDefn(GetGeomFieldDefn(i));
188
0
    }
189
190
0
    return poCopy;
191
0
}
192
193
/************************************************************************/
194
/*                              SetName()                               */
195
/************************************************************************/
196
197
/**
198
 * \brief Change name of this OGRFeatureDefn.
199
 *
200
 * To rename a layer, do not use this function directly, but use
201
 * OGRLayer::Rename() instead.
202
 *
203
 * @param pszName feature definition name
204
 */
205
void OGRFeatureDefn::SetName(const char *pszName)
206
0
{
207
0
    if (m_bSealed)
208
0
    {
209
0
        CPLError(CE_Failure, CPLE_AppDefined,
210
0
                 "OGRFeatureDefn::SetName() not allowed on a sealed object");
211
0
        return;
212
0
    }
213
0
    CPLFree(pszFeatureClassName);
214
0
    pszFeatureClassName = CPLStrdup(pszName);
215
0
}
216
217
/************************************************************************/
218
/*                              GetName()                               */
219
/************************************************************************/
220
221
/**
222
 * \fn const char *OGRFeatureDefn::GetName();
223
 *
224
 * \brief Get name of this OGRFeatureDefn.
225
 *
226
 * This method is the same as the C function OGR_FD_GetName().
227
 *
228
 * @return the name.  This name is internal and should not be modified, or
229
 * freed.
230
 */
231
const char *OGRFeatureDefn::GetName() const
232
0
{
233
0
    return pszFeatureClassName;
234
0
}
235
236
/************************************************************************/
237
/*                           OGR_FD_GetName()                           */
238
/************************************************************************/
239
/**
240
 * \brief Get name of the OGRFeatureDefn passed as an argument.
241
 *
242
 * This function is the same as the C++ method OGRFeatureDefn::GetName().
243
 *
244
 * @param hDefn handle to the feature definition to get the name from.
245
 * @return the name.  This name is internal and should not be modified, or
246
 * freed.
247
 */
248
249
const char *OGR_FD_GetName(OGRFeatureDefnH hDefn)
250
251
0
{
252
0
    return OGRFeatureDefn::FromHandle(hDefn)->GetName();
253
0
}
254
255
/************************************************************************/
256
/*                           GetFieldCount()                            */
257
/************************************************************************/
258
259
/**
260
 * \fn int OGRFeatureDefn::GetFieldCount() const;
261
 *
262
 * \brief Fetch number of fields on this feature.
263
 *
264
 * This method is the same as the C function OGR_FD_GetFieldCount().
265
 * @return count of fields.
266
 */
267
268
int OGRFeatureDefn::GetFieldCount() const
269
0
{
270
0
    return static_cast<int>(apoFieldDefn.size());
271
0
}
272
273
/************************************************************************/
274
/*                        OGR_FD_GetFieldCount()                        */
275
/************************************************************************/
276
277
/**
278
 * \brief Fetch number of fields on the passed feature definition.
279
 *
280
 * This function is the same as the C++ OGRFeatureDefn::GetFieldCount().
281
 *
282
 * @param hDefn handle to the feature definition to get the fields count from.
283
 * @return count of fields.
284
 */
285
286
int OGR_FD_GetFieldCount(OGRFeatureDefnH hDefn)
287
288
0
{
289
0
#ifdef OGRAPISPY_ENABLED
290
0
    if (bOGRAPISpyEnabled)
291
0
        OGRAPISpy_FD_GetFieldCount(hDefn);
292
0
#endif
293
294
0
    return OGRFeatureDefn::FromHandle(hDefn)->GetFieldCount();
295
0
}
296
297
/************************************************************************/
298
/*                            GetFieldDefn()                            */
299
/************************************************************************/
300
301
/**
302
 * \brief Fetch field definition.
303
 *
304
 * This method is the same as the C function OGR_FD_GetFieldDefn().
305
 *
306
 * @param iField the field to fetch, between 0 and GetFieldCount() - 1.
307
 *
308
 * @return a pointer to an internal field definition object or NULL if invalid
309
 * index.  This object should not be modified or freed by the application.
310
 */
311
312
OGRFieldDefn *OGRFeatureDefn::GetFieldDefn(int iField)
313
314
0
{
315
0
    if (iField < 0 || iField >= GetFieldCount())
316
0
    {
317
0
        CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iField);
318
0
        return nullptr;
319
0
    }
320
321
0
    return apoFieldDefn[iField].get();
322
0
}
323
324
/**
325
 * \brief Fetch field definition.
326
 *
327
 * This method is the same as the C function OGR_FD_GetFieldDefn().
328
 *
329
 * @param iField the field to fetch, between 0 and GetFieldCount() - 1.
330
 *
331
 * @return a pointer to an internal field definition object or NULL if invalid
332
 * index.  This object should not be modified or freed by the application.
333
 *
334
 */
335
336
const OGRFieldDefn *OGRFeatureDefn::GetFieldDefn(int iField) const
337
338
0
{
339
0
    if (iField < 0 || iField >= GetFieldCount())
340
0
    {
341
0
        CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iField);
342
0
        return nullptr;
343
0
    }
344
345
0
    return apoFieldDefn[iField].get();
346
0
}
347
348
/************************************************************************/
349
/*                        OGR_FD_GetFieldDefn()                         */
350
/************************************************************************/
351
352
/**
353
 * \brief Fetch field definition of the passed feature definition.
354
 *
355
 * This function is the same as the C++ method
356
 * OGRFeatureDefn::GetFieldDefn().
357
 *
358
 * @param hDefn handle to the feature definition to get the field definition
359
 * from.
360
 * @param iField the field to fetch, between 0 and GetFieldCount()-1.
361
 *
362
 * @return a handle to an internal field definition object or NULL if invalid
363
 * index.  This object should not be modified or freed by the application.
364
 */
365
366
OGRFieldDefnH OGR_FD_GetFieldDefn(OGRFeatureDefnH hDefn, int iField)
367
368
0
{
369
0
    OGRFieldDefnH hFieldDefnH = OGRFieldDefn::ToHandle(
370
0
        OGRFeatureDefn::FromHandle(hDefn)->GetFieldDefn(iField));
371
372
0
#ifdef OGRAPISPY_ENABLED
373
0
    if (bOGRAPISpyEnabled)
374
0
        OGRAPISpy_FD_GetFieldDefn(hDefn, iField, hFieldDefnH);
375
0
#endif
376
377
0
    return hFieldDefnH;
378
0
}
379
380
//! @cond Doxygen_Suppress
381
382
/************************************************************************/
383
/*                       ReserveSpaceForFields()                        */
384
/************************************************************************/
385
386
void OGRFeatureDefn::ReserveSpaceForFields(int nFieldCountIn)
387
0
{
388
0
    apoFieldDefn.reserve(nFieldCountIn);
389
0
}
390
391
//! @endcond
392
393
/************************************************************************/
394
/*                            AddFieldDefn()                            */
395
/************************************************************************/
396
397
/**
398
 * \brief Add a new field definition.
399
 *
400
 * To add a new field definition to a layer definition, do not use this
401
 * function directly, but use OGRLayer::CreateField() instead.
402
 *
403
 * This method should only be called while there are no OGRFeature
404
 * objects in existence based on this OGRFeatureDefn.  The OGRFieldDefn
405
 * passed in is copied, and remains the responsibility of the caller.
406
 *
407
 * This method is the same as the C function OGR_FD_AddFieldDefn().
408
 *
409
 * @param poNewDefn the definition of the new field.
410
 */
411
412
void OGRFeatureDefn::AddFieldDefn(const OGRFieldDefn *poNewDefn)
413
414
0
{
415
0
    if (m_bSealed)
416
0
    {
417
0
        CPLError(
418
0
            CE_Failure, CPLE_AppDefined,
419
0
            "OGRFeatureDefn::AddFieldDefn() not allowed on a sealed object");
420
0
        return;
421
0
    }
422
0
    apoFieldDefn.emplace_back(std::make_unique<OGRFieldDefn>(poNewDefn));
423
0
}
424
425
/**
426
 * \brief Add a new field definition taking ownership of the passed field.
427
 *
428
 * To add a new field definition to a layer definition, do not use this
429
 * function directly, but use OGRLayer::CreateField() instead.
430
 *
431
 * This method should only be called while there are no OGRFeature
432
 * objects in existence based on this OGRFeatureDefn.
433
 *
434
 * @param poNewDefn the definition of the new field.
435
 */
436
437
void OGRFeatureDefn::AddFieldDefn(std::unique_ptr<OGRFieldDefn> &&poNewDefn)
438
0
{
439
0
    if (m_bSealed)
440
0
    {
441
0
        CPLError(
442
0
            CE_Failure, CPLE_AppDefined,
443
0
            "OGRFeatureDefn::AddFieldDefn() not allowed on a sealed object");
444
0
        return;
445
0
    }
446
0
    apoFieldDefn.push_back(std::move(poNewDefn));
447
0
}
448
449
/************************************************************************/
450
/*                        OGR_FD_AddFieldDefn()                         */
451
/************************************************************************/
452
453
/**
454
 * \brief Add a new field definition to the passed feature definition.
455
 *
456
 * To add a new field definition to a layer definition, do not use this
457
 * function directly, but use OGR_L_CreateField() instead.
458
 *
459
 * This function should only be called while there are no OGRFeature
460
 * objects in existence based on this OGRFeatureDefn.  The OGRFieldDefn
461
 * passed in is copied, and remains the responsibility of the caller.
462
 *
463
 * This function is the same as the C++ method OGRFeatureDefn::AddFieldDefn().
464
 *
465
 * @param hDefn handle to the feature definition to add the field definition
466
 * to.
467
 * @param hNewField handle to the new field definition.
468
 */
469
470
void OGR_FD_AddFieldDefn(OGRFeatureDefnH hDefn, OGRFieldDefnH hNewField)
471
472
0
{
473
0
    OGRFeatureDefn::FromHandle(hDefn)->AddFieldDefn(
474
0
        OGRFieldDefn::FromHandle(hNewField));
475
0
}
476
477
/************************************************************************/
478
/*                          DeleteFieldDefn()                           */
479
/************************************************************************/
480
481
/**
482
 * \brief Delete an existing field definition.
483
 *
484
 * To delete an existing field definition from a layer definition, do not use
485
 * this function directly, but use OGRLayer::DeleteField() instead.
486
 *
487
 * This method should only be called while there are no OGRFeature
488
 * objects in existence based on this OGRFeatureDefn.
489
 *
490
 * This method is the same as the C function OGR_FD_DeleteFieldDefn().
491
 *
492
 * @param iField the index of the field definition.
493
 * @return OGRERR_NONE in case of success.
494
 */
495
496
OGRErr OGRFeatureDefn::DeleteFieldDefn(int iField)
497
498
0
{
499
0
    if (m_bSealed)
500
0
    {
501
0
        CPLError(
502
0
            CE_Failure, CPLE_AppDefined,
503
0
            "OGRFeatureDefn::DeleteFieldDefn() not allowed on a sealed object");
504
0
        return OGRERR_FAILURE;
505
0
    }
506
0
    if (iField < 0 || iField >= GetFieldCount())
507
0
        return OGRERR_FAILURE;
508
509
0
    apoFieldDefn.erase(apoFieldDefn.begin() + iField);
510
0
    return OGRERR_NONE;
511
0
}
512
513
/************************************************************************/
514
/*                         StealGeomFieldDefn()                         */
515
/************************************************************************/
516
517
std::unique_ptr<OGRGeomFieldDefn> OGRFeatureDefn::StealGeomFieldDefn(int iField)
518
0
{
519
0
    if (m_bSealed)
520
0
    {
521
0
        CPLError(CE_Failure, CPLE_AppDefined,
522
0
                 "OGRFeatureDefn::StealGeomFieldDefn() not allowed on a sealed "
523
0
                 "object");
524
0
        return nullptr;
525
0
    }
526
0
    if (iField < 0 || iField >= GetGeomFieldCount())
527
0
        return nullptr;
528
529
0
    std::unique_ptr<OGRGeomFieldDefn> poFieldDef =
530
0
        std::move(apoGeomFieldDefn.at(iField));
531
0
    apoGeomFieldDefn.erase(apoGeomFieldDefn.begin() + iField);
532
0
    return poFieldDef;
533
0
}
534
535
/************************************************************************/
536
/*                           StealFieldDefn()                           */
537
/************************************************************************/
538
539
std::unique_ptr<OGRFieldDefn> OGRFeatureDefn::StealFieldDefn(int iField)
540
0
{
541
0
    if (iField < 0 || iField >= GetFieldCount())
542
0
        return nullptr;
543
544
0
    std::unique_ptr<OGRFieldDefn> poFDef = std::move(apoFieldDefn.at(iField));
545
0
    apoFieldDefn.erase(apoFieldDefn.begin() + iField);
546
0
    return poFDef;
547
0
}
548
549
/************************************************************************/
550
/*                       OGR_FD_DeleteFieldDefn()                       */
551
/************************************************************************/
552
553
/**
554
 * \brief Delete an existing field definition.
555
 *
556
 * To delete an existing field definition from a layer definition, do not use
557
 * this function directly, but use OGR_L_DeleteField() instead.
558
 *
559
 * This method should only be called while there are no OGRFeature
560
 * objects in existence based on this OGRFeatureDefn.
561
 *
562
 * This method is the same as the C++ method OGRFeatureDefn::DeleteFieldDefn().
563
 *
564
 * @param hDefn handle to the feature definition.
565
 * @param iField the index of the field definition.
566
 * @return OGRERR_NONE in case of success.
567
 */
568
569
OGRErr OGR_FD_DeleteFieldDefn(OGRFeatureDefnH hDefn, int iField)
570
571
0
{
572
0
    return OGRFeatureDefn::FromHandle(hDefn)->DeleteFieldDefn(iField);
573
0
}
574
575
/************************************************************************/
576
/*                         ReorderFieldDefns()                          */
577
/************************************************************************/
578
579
/**
580
 * \brief Reorder the field definitions in the array of the feature definition
581
 *
582
 * To reorder the field definitions in a layer definition, do not use this
583
 * function directly, but use OGR_L_ReorderFields() instead.
584
 *
585
 * This method should only be called while there are no OGRFeature
586
 * objects in existence based on this OGRFeatureDefn.
587
 *
588
 * This method is the same as the C function OGR_FD_ReorderFieldDefns().
589
 *
590
 * @param panMap an array of GetFieldCount() elements which
591
 * is a permutation of [0, GetFieldCount()-1]. panMap is such that,
592
 * for each field definition at position i after reordering,
593
 * its position before reordering was panMap[i].
594
 * @return OGRERR_NONE in case of success.
595
 */
596
597
OGRErr OGRFeatureDefn::ReorderFieldDefns(const int *panMap)
598
0
{
599
0
    if (m_bSealed)
600
0
    {
601
0
        CPLError(CE_Failure, CPLE_AppDefined,
602
0
                 "OGRFeatureDefn::ReorderFieldDefns() not allowed on a sealed "
603
0
                 "object");
604
0
        return OGRERR_FAILURE;
605
0
    }
606
0
    const int nFieldCount = GetFieldCount();
607
0
    if (nFieldCount == 0)
608
0
        return OGRERR_NONE;
609
610
0
    const OGRErr eErr = OGRCheckPermutation(panMap, nFieldCount);
611
0
    if (eErr != OGRERR_NONE)
612
0
        return eErr;
613
614
0
    std::vector<std::unique_ptr<OGRFieldDefn>> apoFieldDefnNew(nFieldCount);
615
0
    for (int i = 0; i < nFieldCount; i++)
616
0
    {
617
0
        apoFieldDefnNew[i] = std::move(apoFieldDefn[panMap[i]]);
618
0
    }
619
0
    apoFieldDefn = std::move(apoFieldDefnNew);
620
0
    return OGRERR_NONE;
621
0
}
622
623
/************************************************************************/
624
/*                      OGR_FD_ReorderFieldDefns()                      */
625
/************************************************************************/
626
627
/**
628
 * \brief Reorder the field definitions in the array of the feature definition
629
 *
630
 * To reorder the field definitions in a layer definition, do not use this
631
 * function directly, but use OGR_L_ReorderFields() instead.
632
 *
633
 * This method should only be called while there are no OGRFeature
634
 * objects in existence based on this OGRFeatureDefn.
635
 *
636
 * This method is the same as the C++ method
637
 * OGRFeatureDefn::ReorderFieldDefns().
638
 *
639
 * @param hDefn handle to the feature definition.
640
 * @param panMap an array of GetFieldCount() elements which
641
 * is a permutation of [0, GetFieldCount()-1]. panMap is such that,
642
 * for each field definition at position i after reordering,
643
 * its position before reordering was panMap[i].
644
 * @return OGRERR_NONE in case of success.
645
 */
646
647
OGRErr OGR_FD_ReorderFieldDefns(OGRFeatureDefnH hDefn, const int *panMap)
648
649
0
{
650
0
    return OGRFeatureDefn::FromHandle(hDefn)->ReorderFieldDefns(panMap);
651
0
}
652
653
/************************************************************************/
654
/*                         GetGeomFieldCount()                          */
655
/************************************************************************/
656
657
/**
658
 * \fn int OGRFeatureDefn::GetGeomFieldCount() const;
659
 *
660
 * \brief Fetch number of geometry fields on this feature.
661
 *
662
 * This method is the same as the C function OGR_FD_GetGeomFieldCount().
663
 * @return count of geometry fields.
664
 *
665
 */
666
int OGRFeatureDefn::GetGeomFieldCount() const
667
0
{
668
0
    return static_cast<int>(apoGeomFieldDefn.size());
669
0
}
670
671
/************************************************************************/
672
/*                      OGR_FD_GetGeomFieldCount()                      */
673
/************************************************************************/
674
675
/**
676
 * \brief Fetch number of geometry fields on the passed feature definition.
677
 *
678
 * This function is the same as the C++ OGRFeatureDefn::GetGeomFieldCount().
679
 *
680
 * @param hDefn handle to the feature definition to get the fields count from.
681
 * @return count of geometry fields.
682
 *
683
 */
684
685
int OGR_FD_GetGeomFieldCount(OGRFeatureDefnH hDefn)
686
687
0
{
688
0
#ifdef OGRAPISPY_ENABLED
689
0
    if (bOGRAPISpyEnabled)
690
0
        OGRAPISpy_FD_GetGeomFieldCount(hDefn);
691
0
#endif
692
693
0
    return OGRFeatureDefn::FromHandle(hDefn)->GetGeomFieldCount();
694
0
}
695
696
/************************************************************************/
697
/*                          GetGeomFieldDefn()                          */
698
/************************************************************************/
699
700
/**
701
 * \brief Fetch geometry field definition.
702
 *
703
 * This method is the same as the C function OGR_FD_GetGeomFieldDefn().
704
 *
705
 * @param iGeomField the geometry field to fetch, between 0 and
706
 * GetGeomFieldCount() - 1.
707
 *
708
 * @return a pointer to an internal field definition object or NULL if invalid
709
 * index.  This object should not be modified or freed by the application.
710
 *
711
 */
712
713
OGRGeomFieldDefn *OGRFeatureDefn::GetGeomFieldDefn(int iGeomField)
714
715
0
{
716
0
    if (iGeomField < 0 || iGeomField >= GetGeomFieldCount())
717
0
    {
718
0
        CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iGeomField);
719
0
        return nullptr;
720
0
    }
721
722
0
    return apoGeomFieldDefn[iGeomField].get();
723
0
}
724
725
/**
726
 * \brief Fetch geometry field definition.
727
 *
728
 * This method is the same as the C function OGR_FD_GetGeomFieldDefn().
729
 *
730
 * @param iGeomField the geometry field to fetch, between 0 and
731
 * GetGeomFieldCount() - 1.
732
 *
733
 * @return a pointer to an internal field definition object or NULL if invalid
734
 * index.  This object should not be modified or freed by the application.
735
 *
736
 */
737
738
const OGRGeomFieldDefn *OGRFeatureDefn::GetGeomFieldDefn(int iGeomField) const
739
740
0
{
741
0
    if (iGeomField < 0 || iGeomField >= GetGeomFieldCount())
742
0
    {
743
0
        CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iGeomField);
744
0
        return nullptr;
745
0
    }
746
747
0
    return apoGeomFieldDefn[iGeomField].get();
748
0
}
749
750
/************************************************************************/
751
/*                      OGR_FD_GetGeomFieldDefn()                       */
752
/************************************************************************/
753
754
/**
755
 * \brief Fetch geometry field definition of the passed feature definition.
756
 *
757
 * This function is the same as the C++ method
758
 * OGRFeatureDefn::GetGeomFieldDefn().
759
 *
760
 * @param hDefn handle to the feature definition to get the field definition
761
 * from.
762
 * @param iGeomField the geometry field to fetch, between 0 and
763
 * GetGeomFieldCount() - 1.
764
 *
765
 * @return a handle to an internal field definition object or NULL if invalid
766
 * index.  This object should not be modified or freed by the application.
767
 *
768
 */
769
770
OGRGeomFieldDefnH OGR_FD_GetGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField)
771
772
0
{
773
0
    OGRGeomFieldDefnH hGeomField = OGRGeomFieldDefn::ToHandle(
774
0
        OGRFeatureDefn::FromHandle(hDefn)->GetGeomFieldDefn(iGeomField));
775
776
0
#ifdef OGRAPISPY_ENABLED
777
0
    if (bOGRAPISpyEnabled)
778
0
        OGRAPISpy_FD_GetGeomFieldDefn(hDefn, iGeomField, hGeomField);
779
0
#endif
780
781
0
    return hGeomField;
782
0
}
783
784
/************************************************************************/
785
/*                          AddGeomFieldDefn()                          */
786
/************************************************************************/
787
788
/**
789
 * \brief Add a new geometry field definition.
790
 *
791
 * To add a new geometry field definition to a layer definition, do not use this
792
 * function directly, but use OGRLayer::CreateGeomField() instead.
793
 *
794
 * This method does an internal copy of the passed geometry field definition,
795
 * unless bCopy is set to FALSE (in which case it takes ownership of the
796
 * field definition.
797
 *
798
 * This method should only be called while there are no OGRFeature
799
 * objects in existence based on this OGRFeatureDefn.  The OGRGeomFieldDefn
800
 * passed in is copied, and remains the responsibility of the caller.
801
 *
802
 * This method is the same as the C function OGR_FD_AddGeomFieldDefn().
803
 *
804
 * @param poNewDefn the definition of the new geometry field.
805
 *
806
 */
807
808
void OGRFeatureDefn::AddGeomFieldDefn(const OGRGeomFieldDefn *poNewDefn)
809
0
{
810
0
    if (m_bSealed)
811
0
    {
812
0
        CPLError(CE_Failure, CPLE_AppDefined,
813
0
                 "OGRFeatureDefn::AddGeomFieldDefn() not allowed on a sealed "
814
0
                 "object");
815
0
        return;
816
0
    }
817
0
    apoGeomFieldDefn.emplace_back(
818
0
        std::make_unique<OGRGeomFieldDefn>(poNewDefn));
819
0
}
820
821
/**
822
 * \brief Add a new geometry field definition.
823
 *
824
 * To add a new geometry field definition to a layer definition, do not use this
825
 * function directly, but use OGRLayer::CreateGeomField() instead.
826
 *
827
 * This method takes ownership of the passed geometry field definition.
828
 *
829
 * This method should only be called while there are no OGRFeature
830
 * objects in existence based on this OGRFeatureDefn.
831
 *
832
 * @param poNewDefn the definition of the new geometry field.
833
 *
834
 * @since GDAL 3.4
835
 */
836
837
void OGRFeatureDefn::AddGeomFieldDefn(
838
    std::unique_ptr<OGRGeomFieldDefn> &&poNewDefn)
839
0
{
840
0
    apoGeomFieldDefn.emplace_back(std::move(poNewDefn));
841
0
}
842
843
/************************************************************************/
844
/*                      OGR_FD_AddGeomFieldDefn()                       */
845
/************************************************************************/
846
847
/**
848
 * \brief Add a new field definition to the passed feature definition.
849
 *
850
 * To add a new field definition to a layer definition, do not use this
851
 * function directly, but use OGR_L_CreateGeomField() instead.
852
 *
853
 * This function should only be called while there are no OGRFeature
854
 * objects in existence based on this OGRFeatureDefn.  The OGRGeomFieldDefn
855
 * passed in is copied, and remains the responsibility of the caller.
856
 *
857
 * This function is the same as the C++ method
858
 * OGRFeatureDefn::AddGeomFieldDefn().
859
 *
860
 * @param hDefn handle to the feature definition to add the geometry field
861
 * definition to.
862
 * @param hNewGeomField handle to the new field definition.
863
 *
864
 */
865
866
void OGR_FD_AddGeomFieldDefn(OGRFeatureDefnH hDefn,
867
                             OGRGeomFieldDefnH hNewGeomField)
868
869
0
{
870
0
    OGRFeatureDefn::FromHandle(hDefn)->AddGeomFieldDefn(
871
0
        OGRGeomFieldDefn::FromHandle(hNewGeomField));
872
0
}
873
874
/************************************************************************/
875
/*                        DeleteGeomFieldDefn()                         */
876
/************************************************************************/
877
878
/**
879
 * \brief Delete an existing geometry field definition.
880
 *
881
 * To delete an existing field definition from a layer definition, do not use
882
 * this function directly, but use OGRLayer::DeleteGeomField() instead.
883
 *
884
 * This method should only be called while there are no OGRFeature
885
 * objects in existence based on this OGRFeatureDefn.
886
 *
887
 * This method is the same as the C function OGR_FD_DeleteGeomFieldDefn().
888
 *
889
 * @param iGeomField the index of the geometry field definition.
890
 * @return OGRERR_NONE in case of success.
891
 *
892
 */
893
894
OGRErr OGRFeatureDefn::DeleteGeomFieldDefn(int iGeomField)
895
896
0
{
897
0
    if (m_bSealed)
898
0
    {
899
0
        CPLError(CE_Failure, CPLE_AppDefined,
900
0
                 "OGRFeatureDefn::DeleteGeomFieldDefn() not allowed on a "
901
0
                 "sealed object");
902
0
        return OGRERR_FAILURE;
903
0
    }
904
0
    if (iGeomField < 0 || iGeomField >= GetGeomFieldCount())
905
0
        return OGRERR_FAILURE;
906
907
0
    apoGeomFieldDefn.erase(apoGeomFieldDefn.begin() + iGeomField);
908
0
    return OGRERR_NONE;
909
0
}
910
911
/************************************************************************/
912
/*                     OGR_FD_DeleteGeomFieldDefn()                     */
913
/************************************************************************/
914
915
/**
916
 * \brief Delete an existing geometry field definition.
917
 *
918
 * To delete an existing geometry field definition from a layer definition, do
919
 * not use this function directly, but use OGR_L_DeleteGeomField() instead
920
 * (*not implemented yet*).
921
 *
922
 * This method should only be called while there are no OGRFeature
923
 * objects in existence based on this OGRFeatureDefn.
924
 *
925
 * This method is the same as the C++ method
926
 * OGRFeatureDefn::DeleteGeomFieldDefn().
927
 *
928
 * @param hDefn handle to the feature definition.
929
 * @param iGeomField the index of the geometry field definition.
930
 * @return OGRERR_NONE in case of success.
931
 *
932
 */
933
934
OGRErr OGR_FD_DeleteGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField)
935
936
0
{
937
0
    return OGRFeatureDefn::FromHandle(hDefn)->DeleteGeomFieldDefn(iGeomField);
938
0
}
939
940
/************************************************************************/
941
/*                         GetGeomFieldIndex()                          */
942
/************************************************************************/
943
944
/**
945
 * \brief Find geometry field by name.
946
 *
947
 * The geometry field index of the first geometry field matching the passed
948
 * field name (case insensitively) is returned.
949
 *
950
 * This method is the same as the C function OGR_FD_GetGeomFieldIndex().
951
 *
952
 * @param pszGeomFieldName the geometry field name to search for.
953
 *
954
 * @return the geometry field index, or -1 if no match found.
955
 */
956
957
int OGRFeatureDefn::GetGeomFieldIndex(const char *pszGeomFieldName) const
958
959
0
{
960
0
    const int nGeomFieldCount = GetGeomFieldCount();
961
0
    for (int i = 0; i < nGeomFieldCount; i++)
962
0
    {
963
0
        const OGRGeomFieldDefn *poGFldDefn = GetGeomFieldDefn(i);
964
0
        if (poGFldDefn != nullptr &&
965
0
            EQUAL(pszGeomFieldName, poGFldDefn->GetNameRef()))
966
0
            return i;
967
0
    }
968
969
0
    return -1;
970
0
}
971
972
/************************************************************************/
973
/*                      OGR_FD_GetGeomFieldIndex()                      */
974
/************************************************************************/
975
/**
976
 * \brief Find geometry field by name.
977
 *
978
 * The geometry field index of the first geometry field matching the passed
979
 * field name (case insensitively) is returned.
980
 *
981
 * This function is the same as the C++ method
982
 * OGRFeatureDefn::GetGeomFieldIndex.
983
 *
984
 * @param hDefn handle to the feature definition to get field index from.
985
 * @param pszGeomFieldName the geometry field name to search for.
986
 *
987
 * @return the geometry field index, or -1 if no match found.
988
 */
989
990
int OGR_FD_GetGeomFieldIndex(OGRFeatureDefnH hDefn,
991
                             const char *pszGeomFieldName)
992
993
0
{
994
0
#ifdef OGRAPISPY_ENABLED
995
0
    if (bOGRAPISpyEnabled)
996
0
        OGRAPISpy_FD_GetGeomFieldIndex(hDefn, pszGeomFieldName);
997
0
#endif
998
999
0
    return OGRFeatureDefn::FromHandle(hDefn)->GetGeomFieldIndex(
1000
0
        pszGeomFieldName);
1001
0
}
1002
1003
/************************************************************************/
1004
/*                            GetGeomType()                             */
1005
/************************************************************************/
1006
1007
/**
1008
 * \fn OGRwkbGeometryType OGRFeatureDefn::GetGeomType() const;
1009
 *
1010
 * \brief Fetch the geometry base type.
1011
 *
1012
 * Note that some drivers are unable to determine a specific geometry
1013
 * type for a layer, in which case wkbUnknown is returned.  A value of
1014
 * wkbNone indicates no geometry is available for the layer at all.
1015
 * Many drivers do not properly mark the geometry
1016
 * type as 25D even if some or all geometries are in fact 25D.  A few (broken)
1017
 * drivers return wkbPolygon for layers that also include wkbMultiPolygon.
1018
 *
1019
 * This method returns GetGeomFieldDefn(0)->GetType().
1020
 *
1021
 * This method is the same as the C function OGR_FD_GetGeomType().
1022
 *
1023
 * @return the base type for all geometry related to this definition.
1024
 */
1025
OGRwkbGeometryType OGRFeatureDefn::GetGeomType() const
1026
0
{
1027
0
    if (GetGeomFieldCount() == 0)
1028
0
        return wkbNone;
1029
0
    const OGRGeomFieldDefn *poGFldDefn = GetGeomFieldDefn(0);
1030
0
    if (poGFldDefn == nullptr)
1031
0
        return wkbNone;
1032
0
    OGRwkbGeometryType eType = poGFldDefn->GetType();
1033
0
    if (eType == (/*wkbUnknown |*/ wkb25DBitInternalUse) &&
1034
0
        CPLTestBool(CPLGetConfigOption("QGIS_HACK", "NO")))
1035
0
        eType = wkbUnknown;
1036
0
    return eType;
1037
0
}
1038
1039
/************************************************************************/
1040
/*                         OGR_FD_GetGeomType()                         */
1041
/************************************************************************/
1042
/**
1043
 * \brief Fetch the geometry base type of the passed feature definition.
1044
 *
1045
 * This function is the same as the C++ method OGRFeatureDefn::GetGeomType().
1046
 *
1047
 * This method returns GetGeomFieldDefn(0)->GetType().
1048
 *
1049
 * @param hDefn handle to the feature definition to get the geometry type from.
1050
 * @return the base type for all geometry related to this definition.
1051
 */
1052
1053
OGRwkbGeometryType OGR_FD_GetGeomType(OGRFeatureDefnH hDefn)
1054
1055
0
{
1056
0
    OGRwkbGeometryType eType = OGRFeatureDefn::FromHandle(hDefn)->GetGeomType();
1057
0
    if (OGR_GT_IsNonLinear(eType) && !OGRGetNonLinearGeometriesEnabledFlag())
1058
0
    {
1059
0
        eType = OGR_GT_GetLinear(eType);
1060
0
    }
1061
0
#ifdef OGRAPISPY_ENABLED
1062
0
    if (bOGRAPISpyEnabled)
1063
0
        OGRAPISpy_FD_GetGeomType(hDefn);
1064
0
#endif
1065
1066
0
    return eType;
1067
0
}
1068
1069
/************************************************************************/
1070
/*                            SetGeomType()                             */
1071
/************************************************************************/
1072
1073
/**
1074
 * \brief Assign the base geometry type for this layer.
1075
 *
1076
 * All geometry objects using this type must be of the defined type or
1077
 * a derived type.  The default upon creation is wkbUnknown which allows for
1078
 * any geometry type.  The geometry type should generally not be changed
1079
 * after any OGRFeatures have been created against this definition.
1080
 *
1081
 * This method is the same as the C function OGR_FD_SetGeomType().
1082
 *
1083
 * This method calls GetGeomFieldDefn(0)->SetType().
1084
 *
1085
 * @param eNewType the new type to assign.
1086
 */
1087
1088
void OGRFeatureDefn::SetGeomType(OGRwkbGeometryType eNewType)
1089
1090
0
{
1091
0
    if (m_bSealed)
1092
0
    {
1093
0
        CPLError(
1094
0
            CE_Failure, CPLE_AppDefined,
1095
0
            "OGRFeatureDefn::SetGeomType() not allowed on a sealed object");
1096
0
        return;
1097
0
    }
1098
0
    const int nGeomFieldCount = GetGeomFieldCount();
1099
0
    if (nGeomFieldCount > 0)
1100
0
    {
1101
0
        if (nGeomFieldCount == 1 && eNewType == wkbNone)
1102
0
            DeleteGeomFieldDefn(0);
1103
0
        else
1104
0
            GetGeomFieldDefn(0)->SetType(eNewType);
1105
0
    }
1106
0
    else if (eNewType != wkbNone)
1107
0
    {
1108
0
        OGRGeomFieldDefn oGeomFieldDefn("", eNewType);
1109
0
        AddGeomFieldDefn(&oGeomFieldDefn);
1110
0
    }
1111
0
}
1112
1113
/************************************************************************/
1114
/*                         OGR_FD_SetGeomType()                         */
1115
/************************************************************************/
1116
1117
/**
1118
 * \brief Assign the base geometry type for the passed layer (the same as the
1119
 * feature definition).
1120
 *
1121
 * All geometry objects using this type must be of the defined type or
1122
 * a derived type.  The default upon creation is wkbUnknown which allows for
1123
 * any geometry type.  The geometry type should generally not be changed
1124
 * after any OGRFeatures have been created against this definition.
1125
 *
1126
 * This function is the same as the C++ method OGRFeatureDefn::SetGeomType().
1127
 *
1128
 * This method calls GetGeomFieldDefn(0)->SetType().
1129
 *
1130
 * @param hDefn handle to the layer or feature definition to set the geometry
1131
 * type to.
1132
 * @param eType the new type to assign.
1133
 */
1134
1135
void OGR_FD_SetGeomType(OGRFeatureDefnH hDefn, OGRwkbGeometryType eType)
1136
1137
0
{
1138
0
    OGRFeatureDefn::FromHandle(hDefn)->SetGeomType(eType);
1139
0
}
1140
1141
/************************************************************************/
1142
/*                             Reference()                              */
1143
/************************************************************************/
1144
1145
/**
1146
 * \fn int OGRFeatureDefn::Reference();
1147
 *
1148
 * \brief Increments the reference count by one.
1149
 *
1150
 * The reference count is used keep track of the number of OGRFeature
1151
 * objects referencing this definition.
1152
 *
1153
 * This method is the same as the C function OGR_FD_Reference().
1154
 *
1155
 * @return the updated reference count.
1156
 */
1157
1158
/************************************************************************/
1159
/*                          OGR_FD_Reference()                          */
1160
/************************************************************************/
1161
/**
1162
 * \brief Increments the reference count by one.
1163
 *
1164
 * The reference count is used keep track of the number of OGRFeature
1165
 * objects referencing this definition.
1166
 *
1167
 * This function is the same as the C++ method OGRFeatureDefn::Reference().
1168
 *
1169
 * @param hDefn handle to the feature definition on witch OGRFeature are
1170
 * based on.
1171
 * @return the updated reference count.
1172
 */
1173
1174
int OGR_FD_Reference(OGRFeatureDefnH hDefn)
1175
1176
0
{
1177
0
    return OGRFeatureDefn::FromHandle(hDefn)->Reference();
1178
0
}
1179
1180
/************************************************************************/
1181
/*                            Dereference()                             */
1182
/************************************************************************/
1183
1184
/**
1185
 * \fn int OGRFeatureDefn::Dereference();
1186
 *
1187
 * \brief Decrements the reference count by one.
1188
 *
1189
 * \warning This method does not destroy the object when the reference count
1190
 *          is zero. You generally want to use Release() instead.
1191
 *
1192
 * This method is the same as the C function OGR_FD_Dereference().
1193
 *
1194
 * @return the updated reference count.
1195
 */
1196
1197
/************************************************************************/
1198
/*                         OGR_FD_Dereference()                         */
1199
/************************************************************************/
1200
1201
/**
1202
 * \brief Decrements the reference count by one.
1203
 *
1204
 * \warning This method does not destroy the object when the reference count
1205
 *          is zero. You generally want to use OGR_FD_Release() instead.
1206
1207
 * This function is the same as the C++ method OGRFeatureDefn::Dereference().
1208
 *
1209
 * @param hDefn handle to the feature definition on witch OGRFeature are
1210
 * based on.
1211
 * @return the updated reference count.
1212
 */
1213
1214
int OGR_FD_Dereference(OGRFeatureDefnH hDefn)
1215
1216
0
{
1217
0
#ifdef __GNUC__
1218
0
#pragma GCC diagnostic push
1219
0
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1220
0
#endif
1221
0
    return OGRFeatureDefn::FromHandle(hDefn)->Dereference();
1222
0
#ifdef __GNUC__
1223
0
#pragma GCC diagnostic pop
1224
0
#endif
1225
0
}
1226
1227
/************************************************************************/
1228
/*                         GetReferenceCount()                          */
1229
/************************************************************************/
1230
1231
/**
1232
 * \fn int OGRFeatureDefn::GetReferenceCount();
1233
 *
1234
 * \brief Fetch current reference count.
1235
 *
1236
 * This method is the same as the C function OGR_FD_GetReferenceCount().
1237
 *
1238
 * @return the current reference count.
1239
 */
1240
1241
/************************************************************************/
1242
/*                      OGR_FD_GetReferenceCount()                      */
1243
/************************************************************************/
1244
1245
/**
1246
 * \brief Fetch current reference count.
1247
 *
1248
 * This function is the same as the C++ method
1249
 * OGRFeatureDefn::GetReferenceCount().
1250
 *
1251
 * @param hDefn handle to the feature definition on witch OGRFeature are
1252
 * based on.
1253
 * @return the current reference count.
1254
 */
1255
1256
int OGR_FD_GetReferenceCount(OGRFeatureDefnH hDefn)
1257
1258
0
{
1259
0
    return OGRFeatureDefn::FromHandle(hDefn)->GetReferenceCount();
1260
0
}
1261
1262
/************************************************************************/
1263
/*                           GetFieldIndex()                            */
1264
/************************************************************************/
1265
1266
/**
1267
 * \brief Find field by name.
1268
 *
1269
 * The field index of the first field matching the passed field name (case
1270
 * insensitively) is returned.
1271
 *
1272
 * This method is the same as the C function OGR_FD_GetFieldIndex().
1273
 *
1274
 * @param pszFieldName the field name to search for.
1275
 *
1276
 * @return the field index, or -1 if no match found.
1277
 */
1278
1279
int OGRFeatureDefn::GetFieldIndex(const char *pszFieldName) const
1280
1281
0
{
1282
0
    const int nFieldCount = GetFieldCount();
1283
0
    for (int i = 0; i < nFieldCount; i++)
1284
0
    {
1285
0
        const OGRFieldDefn *poFDefn = GetFieldDefn(i);
1286
0
        if (poFDefn != nullptr && EQUAL(pszFieldName, poFDefn->GetNameRef()))
1287
0
            return i;
1288
0
    }
1289
1290
0
    return -1;
1291
0
}
1292
1293
/************************************************************************/
1294
/*                     GetFieldIndexCaseSensitive()                     */
1295
/************************************************************************/
1296
1297
/**
1298
 * \brief Find field by name, in a case sensitive way.
1299
 *
1300
 * The field index of the first field matching the passed field name is
1301
 * returned.
1302
 *
1303
 * @param pszFieldName the field name to search for.
1304
 *
1305
 * @return the field index, or -1 if no match found.
1306
 */
1307
1308
int OGRFeatureDefn::GetFieldIndexCaseSensitive(const char *pszFieldName) const
1309
1310
0
{
1311
0
    const int nFieldCount = GetFieldCount();
1312
0
    for (int i = 0; i < nFieldCount; i++)
1313
0
    {
1314
0
        const OGRFieldDefn *poFDefn = GetFieldDefn(i);
1315
0
        if (poFDefn != nullptr &&
1316
0
            strcmp(pszFieldName, poFDefn->GetNameRef()) == 0)
1317
0
        {
1318
0
            return i;
1319
0
        }
1320
0
    }
1321
1322
0
    return -1;
1323
0
}
1324
1325
/************************************************************************/
1326
/*                        OGR_FD_GetFieldIndex()                        */
1327
/************************************************************************/
1328
/**
1329
 * \brief Find field by name.
1330
 *
1331
 * The field index of the first field matching the passed field name (case
1332
 * insensitively) is returned.
1333
 *
1334
 * This function is the same as the C++ method OGRFeatureDefn::GetFieldIndex.
1335
 *
1336
 * @param hDefn handle to the feature definition to get field index from.
1337
 * @param pszFieldName the field name to search for.
1338
 *
1339
 * @return the field index, or -1 if no match found.
1340
 */
1341
1342
int OGR_FD_GetFieldIndex(OGRFeatureDefnH hDefn, const char *pszFieldName)
1343
1344
0
{
1345
0
#ifdef OGRAPISPY_ENABLED
1346
0
    if (bOGRAPISpyEnabled)
1347
0
        OGRAPISpy_FD_GetFieldIndex(hDefn, pszFieldName);
1348
0
#endif
1349
1350
0
    return OGRFeatureDefn::FromHandle(hDefn)->GetFieldIndex(pszFieldName);
1351
0
}
1352
1353
/************************************************************************/
1354
/*                         IsGeometryIgnored()                          */
1355
/************************************************************************/
1356
1357
/**
1358
 * \fn int OGRFeatureDefn::IsGeometryIgnored() const;
1359
 *
1360
 * \brief Determine whether the geometry can be omitted when fetching features
1361
 *
1362
 * This method is the same as the C function OGR_FD_IsGeometryIgnored().
1363
 *
1364
 * This method returns
1365
 * GetGeomFieldDefn(0)->IsIgnored().
1366
 *
1367
 * @return ignore state
1368
 */
1369
1370
int OGRFeatureDefn::IsGeometryIgnored() const
1371
0
{
1372
0
    if (GetGeomFieldCount() == 0)
1373
0
        return FALSE;
1374
0
    const OGRGeomFieldDefn *poGFldDefn = GetGeomFieldDefn(0);
1375
0
    if (poGFldDefn == nullptr)
1376
0
        return FALSE;
1377
0
    return poGFldDefn->IsIgnored();
1378
0
}
1379
1380
/************************************************************************/
1381
/*                      OGR_FD_IsGeometryIgnored()                      */
1382
/************************************************************************/
1383
1384
/**
1385
 * \brief Determine whether the geometry can be omitted when fetching features
1386
 *
1387
 * This function is the same as the C++ method
1388
 * OGRFeatureDefn::IsGeometryIgnored().
1389
 *
1390
 * This method returns
1391
 * GetGeomFieldDefn(0)->IsIgnored().
1392
 *
1393
 * @param hDefn handle to the feature definition on witch OGRFeature are
1394
 * based on.
1395
 * @return ignore state
1396
 */
1397
1398
int OGR_FD_IsGeometryIgnored(OGRFeatureDefnH hDefn)
1399
0
{
1400
0
    return OGRFeatureDefn::FromHandle(hDefn)->IsGeometryIgnored();
1401
0
}
1402
1403
/************************************************************************/
1404
/*                         SetGeometryIgnored()                         */
1405
/************************************************************************/
1406
1407
/**
1408
 * \fn void OGRFeatureDefn::SetGeometryIgnored( int bIgnore );
1409
 *
1410
 * \brief Set whether the geometry can be omitted when fetching features
1411
 *
1412
 * This method is the same as the C function OGR_FD_SetGeometryIgnored().
1413
 *
1414
 * This method calls GetGeomFieldDefn(0)->SetIgnored().
1415
 *
1416
 * @param bIgnore ignore state
1417
 */
1418
1419
void OGRFeatureDefn::SetGeometryIgnored(int bIgnore)
1420
0
{
1421
0
    if (GetGeomFieldCount() > 0)
1422
0
    {
1423
0
        OGRGeomFieldDefn *poGFldDefn = GetGeomFieldDefn(0);
1424
0
        if (poGFldDefn != nullptr)
1425
0
            poGFldDefn->SetIgnored(bIgnore);
1426
0
    }
1427
0
}
1428
1429
/************************************************************************/
1430
/*                     OGR_FD_SetGeometryIgnored()                      */
1431
/************************************************************************/
1432
1433
/**
1434
 * \brief Set whether the geometry can be omitted when fetching features
1435
 *
1436
 * This function is the same as the C++ method
1437
 * OGRFeatureDefn::SetGeometryIgnored().
1438
 *
1439
 * This method calls GetGeomFieldDefn(0)->SetIgnored().
1440
 *
1441
 * @param hDefn handle to the feature definition on witch OGRFeature are
1442
 * based on.
1443
 * @param bIgnore ignore state
1444
 */
1445
1446
void OGR_FD_SetGeometryIgnored(OGRFeatureDefnH hDefn, int bIgnore)
1447
0
{
1448
0
    OGRFeatureDefn::FromHandle(hDefn)->SetGeometryIgnored(bIgnore);
1449
0
}
1450
1451
/************************************************************************/
1452
/*                           IsStyleIgnored()                           */
1453
/************************************************************************/
1454
1455
/**
1456
 * \fn int OGRFeatureDefn::IsStyleIgnored() const;
1457
 *
1458
 * \brief Determine whether the style can be omitted when fetching features
1459
 *
1460
 * This method is the same as the C function OGR_FD_IsStyleIgnored().
1461
 *
1462
 * @return ignore state
1463
 */
1464
1465
/************************************************************************/
1466
/*                       OGR_FD_IsStyleIgnored()                        */
1467
/************************************************************************/
1468
1469
/**
1470
 * \brief Determine whether the style can be omitted when fetching features
1471
 *
1472
 * This function is the same as the C++ method
1473
 * OGRFeatureDefn::IsStyleIgnored().
1474
 *
1475
 * @param hDefn handle to the feature definition on which OGRFeature are
1476
 * based on.
1477
 * @return ignore state
1478
 */
1479
1480
int OGR_FD_IsStyleIgnored(OGRFeatureDefnH hDefn)
1481
0
{
1482
0
    return OGRFeatureDefn::FromHandle(hDefn)->IsStyleIgnored();
1483
0
}
1484
1485
/************************************************************************/
1486
/*                          SetStyleIgnored()                           */
1487
/************************************************************************/
1488
1489
/**
1490
 * \fn void OGRFeatureDefn::SetStyleIgnored( int bIgnore );
1491
 *
1492
 * \brief Set whether the style can be omitted when fetching features
1493
 *
1494
 * This method is the same as the C function OGR_FD_SetStyleIgnored().
1495
 *
1496
 * @param bIgnore ignore state
1497
 */
1498
1499
/************************************************************************/
1500
/*                       OGR_FD_SetStyleIgnored()                       */
1501
/************************************************************************/
1502
1503
/**
1504
 * \brief Set whether the style can be omitted when fetching features
1505
 *
1506
 * This function is the same as the C++ method
1507
 * OGRFeatureDefn::SetStyleIgnored().
1508
 *
1509
 * @param hDefn handle to the feature definition on witch OGRFeature are
1510
 * based on.
1511
 * @param bIgnore ignore state
1512
 */
1513
1514
void OGR_FD_SetStyleIgnored(OGRFeatureDefnH hDefn, int bIgnore)
1515
0
{
1516
0
    OGRFeatureDefn::FromHandle(hDefn)->SetStyleIgnored(CPL_TO_BOOL(bIgnore));
1517
0
}
1518
1519
/************************************************************************/
1520
/*                         CreateFeatureDefn()                          */
1521
/************************************************************************/
1522
1523
/** Create a new feature definition object.
1524
 * @param pszName name
1525
 * @return new feature definition object.
1526
 */
1527
OGRFeatureDefn *OGRFeatureDefn::CreateFeatureDefn(const char *pszName)
1528
1529
0
{
1530
0
    return new OGRFeatureDefn(pszName);
1531
0
}
1532
1533
/************************************************************************/
1534
/*                         DestroyFeatureDefn()                         */
1535
/************************************************************************/
1536
1537
/** Destroy a feature definition.
1538
 * @param poDefn feature definition.
1539
 */
1540
void OGRFeatureDefn::DestroyFeatureDefn(OGRFeatureDefn *poDefn)
1541
1542
0
{
1543
0
    delete poDefn;
1544
0
}
1545
1546
/************************************************************************/
1547
/*                               IsSame()                               */
1548
/************************************************************************/
1549
1550
/**
1551
 * \brief Test if the feature definition is identical to the other one.
1552
 *
1553
 * @param poOtherFeatureDefn the other feature definition to compare to.
1554
 * @return TRUE if the feature definition is identical to the other one.
1555
 */
1556
1557
int OGRFeatureDefn::IsSame(const OGRFeatureDefn *poOtherFeatureDefn) const
1558
0
{
1559
0
    const int nFieldCount = GetFieldCount();
1560
0
    const int nGeomFieldCount = GetGeomFieldCount();
1561
0
    if (strcmp(GetName(), poOtherFeatureDefn->GetName()) == 0 &&
1562
0
        nFieldCount == poOtherFeatureDefn->GetFieldCount() &&
1563
0
        nGeomFieldCount == poOtherFeatureDefn->GetGeomFieldCount())
1564
0
    {
1565
0
        for (int i = 0; i < nFieldCount; i++)
1566
0
        {
1567
0
            const OGRFieldDefn *poFldDefn = GetFieldDefn(i);
1568
0
            const OGRFieldDefn *poOtherFldDefn =
1569
0
                poOtherFeatureDefn->GetFieldDefn(i);
1570
0
            if (!poFldDefn->IsSame(poOtherFldDefn))
1571
0
            {
1572
0
                return FALSE;
1573
0
            }
1574
0
        }
1575
0
        for (int i = 0; i < nGeomFieldCount; i++)
1576
0
        {
1577
0
            const OGRGeomFieldDefn *poGFldDefn = GetGeomFieldDefn(i);
1578
0
            const OGRGeomFieldDefn *poOtherGFldDefn =
1579
0
                poOtherFeatureDefn->GetGeomFieldDefn(i);
1580
0
            if (!poGFldDefn->IsSame(poOtherGFldDefn))
1581
0
            {
1582
0
                return FALSE;
1583
0
            }
1584
0
        }
1585
0
        return TRUE;
1586
0
    }
1587
0
    return FALSE;
1588
0
}
1589
1590
/************************************************************************/
1591
/*                           OGR_FD_IsSame()                            */
1592
/************************************************************************/
1593
1594
/**
1595
 * \brief Test if the feature definition is identical to the other one.
1596
 *
1597
 * @param hFDefn handle to the feature definition on witch OGRFeature are
1598
 * based on.
1599
 * @param hOtherFDefn handle to the other feature definition to compare to.
1600
 * @return TRUE if the feature definition is identical to the other one.
1601
 *
1602
 */
1603
1604
int OGR_FD_IsSame(OGRFeatureDefnH hFDefn, OGRFeatureDefnH hOtherFDefn)
1605
0
{
1606
0
    VALIDATE_POINTER1(hFDefn, "OGR_FD_IsSame", FALSE);
1607
0
    VALIDATE_POINTER1(hOtherFDefn, "OGR_FD_IsSame", FALSE);
1608
1609
0
    return OGRFeatureDefn::FromHandle(hFDefn)->IsSame(
1610
0
        OGRFeatureDefn::FromHandle(hOtherFDefn));
1611
0
}
1612
1613
/************************************************************************/
1614
/*                        ComputeMapForSetFrom()                        */
1615
/************************************************************************/
1616
1617
/**
1618
 * \brief Compute the map from source to target field that can be passed to
1619
 * SetFrom().
1620
 *
1621
 * @param poSrcFDefn the feature definition of source features later passed to
1622
 * SetFrom()
1623
 *
1624
 * @param bForgiving true if the operation should continue despite lacking
1625
 * output fields matching some of the source fields.
1626
 *
1627
 * @return an array of size poSrcFDefn->GetFieldCount() if everything succeeds,
1628
 * or empty in case a source field definition was not found in the target layer
1629
 * and bForgiving == true.
1630
 *
1631
 */
1632
1633
std::vector<int>
1634
OGRFeatureDefn::ComputeMapForSetFrom(const OGRFeatureDefn *poSrcFDefn,
1635
                                     bool bForgiving) const
1636
0
{
1637
0
    std::map<CPLString, int> oMapNameToTargetFieldIndex;
1638
0
    std::map<CPLString, int> oMapNameToTargetFieldIndexUC;
1639
0
    const int nFieldCount = GetFieldCount();
1640
0
    for (int i = 0; i < nFieldCount; i++)
1641
0
    {
1642
0
        const OGRFieldDefn *poFldDefn = GetFieldDefn(i);
1643
0
        if (poFldDefn == nullptr)
1644
0
            continue;
1645
0
        const char *pszName = poFldDefn->GetNameRef();
1646
1647
        // In the insane case where there are several matches, arbitrarily
1648
        // decide for the first one (preserve past behavior)
1649
0
        if (oMapNameToTargetFieldIndex.find(pszName) ==
1650
0
            oMapNameToTargetFieldIndex.end())
1651
0
        {
1652
0
            oMapNameToTargetFieldIndex[pszName] = i;
1653
0
        }
1654
0
    }
1655
0
    std::vector<int> aoMapSrcToTargetIdx;
1656
0
    const int nSrcFieldCount = poSrcFDefn->GetFieldCount();
1657
0
    aoMapSrcToTargetIdx.resize(nSrcFieldCount);
1658
0
    for (int i = 0; i < nSrcFieldCount; i++)
1659
0
    {
1660
0
        const OGRFieldDefn *poSrcFldDefn = poSrcFDefn->GetFieldDefn(i);
1661
0
        if (poSrcFldDefn == nullptr)
1662
0
            continue;
1663
0
        const char *pszSrcName = poSrcFldDefn->GetNameRef();
1664
1665
0
        auto oIter = oMapNameToTargetFieldIndex.find(pszSrcName);
1666
0
        if (oIter == oMapNameToTargetFieldIndex.end())
1667
0
        {
1668
            // Build case insensitive map only if needed
1669
0
            if (oMapNameToTargetFieldIndexUC.empty())
1670
0
            {
1671
0
                for (int j = 0; j < nFieldCount; j++)
1672
0
                {
1673
0
                    const OGRFieldDefn *poFldDefn = GetFieldDefn(j);
1674
0
                    if (poFldDefn == nullptr)
1675
0
                        continue;
1676
0
                    oMapNameToTargetFieldIndexUC
1677
0
                        [CPLString(poFldDefn->GetNameRef()).toupper()] = j;
1678
0
                }
1679
0
            }
1680
0
            oIter = oMapNameToTargetFieldIndexUC.find(
1681
0
                CPLString(pszSrcName).toupper());
1682
0
            if (oIter == oMapNameToTargetFieldIndexUC.end())
1683
0
            {
1684
0
                if (!bForgiving)
1685
0
                {
1686
0
                    return std::vector<int>();
1687
0
                }
1688
0
                aoMapSrcToTargetIdx[i] = -1;
1689
0
            }
1690
0
            else
1691
0
            {
1692
0
                aoMapSrcToTargetIdx[i] = oIter->second;
1693
0
            }
1694
0
        }
1695
0
        else
1696
0
        {
1697
0
            aoMapSrcToTargetIdx[i] = oIter->second;
1698
0
        }
1699
0
    }
1700
0
    return aoMapSrcToTargetIdx;
1701
0
}
1702
1703
/************************************************************************/
1704
/*                        OGRFeatureDefn::Seal()                        */
1705
/************************************************************************/
1706
1707
/** Seal a OGRFeatureDefn.
1708
 *
1709
 * A sealed OGRFeatureDefn can not be modified while it is sealed.
1710
 *
1711
 * This method also call OGRFieldDefn::Seal() and OGRGeomFieldDefn::Seal()
1712
 * on its fields and geometry fields.
1713
 *
1714
 * This method should only be called by driver implementations.
1715
 *
1716
 * @param bSealFields Whether fields and geometry fields should be sealed.
1717
 *                    This is generally desirable, but in case of deferred
1718
 *                    resolution of them, this parameter should be set to false.
1719
 * @since GDAL 3.9
1720
 */
1721
void OGRFeatureDefn::Seal(bool bSealFields)
1722
0
{
1723
0
    if (m_bSealed)
1724
0
    {
1725
0
        CPLError(CE_Failure, CPLE_AppDefined,
1726
0
                 "OGRFeatureDefn::Seal(): the object is already sealed");
1727
0
        return;
1728
0
    }
1729
0
    if (bSealFields)
1730
0
    {
1731
0
        const int nFieldCount = GetFieldCount();
1732
0
        for (int i = 0; i < nFieldCount; ++i)
1733
0
            GetFieldDefn(i)->Seal();
1734
0
        const int nGeomFieldCount = GetGeomFieldCount();
1735
0
        for (int i = 0; i < nGeomFieldCount; ++i)
1736
0
            GetGeomFieldDefn(i)->Seal();
1737
0
    }
1738
0
    m_bSealed = true;
1739
0
}
1740
1741
/************************************************************************/
1742
/*                       OGRFeatureDefn::Unseal()                       */
1743
/************************************************************************/
1744
1745
/** Unseal a OGRFeatureDefn.
1746
 *
1747
 * Undo OGRFeatureDefn::Seal()
1748
 *
1749
 * This method also call OGRFieldDefn::Unseal() and OGRGeomFieldDefn::Unseal()
1750
 * on its fields and geometry fields.
1751
 *
1752
 * Using GetTemporaryUnsealer() is recommended for most use cases.
1753
 *
1754
 * This method should only be called by driver implementations.
1755
 *
1756
 * @param bUnsealFields Whether fields and geometry fields should be unsealed.
1757
 *                      This is generally desirable, but in case of deferred
1758
 *                      resolution of them, this parameter should be set to
1759
 * false.
1760
 * @since GDAL 3.9
1761
 */
1762
void OGRFeatureDefn::Unseal(bool bUnsealFields)
1763
0
{
1764
0
    if (!m_bSealed)
1765
0
    {
1766
0
        CPLError(CE_Failure, CPLE_AppDefined,
1767
0
                 "OGRFeatureDefn::Unseal(): the object is already unsealed");
1768
0
        return;
1769
0
    }
1770
0
    m_bSealed = false;
1771
0
    if (bUnsealFields)
1772
0
    {
1773
0
        const int nFieldCount = GetFieldCount();
1774
0
        for (int i = 0; i < nFieldCount; ++i)
1775
0
            GetFieldDefn(i)->Unseal();
1776
0
        const int nGeomFieldCount = GetGeomFieldCount();
1777
0
        for (int i = 0; i < nGeomFieldCount; ++i)
1778
0
            GetGeomFieldDefn(i)->Unseal();
1779
0
    }
1780
0
}
1781
1782
/************************************************************************/
1783
/*                OGRFeatureDefn::GetTemporaryUnsealer()                */
1784
/************************************************************************/
1785
1786
/** Return an object that temporary unseals the OGRFeatureDefn
1787
 *
1788
 * The returned object calls Unseal() initially, and when it is destroyed
1789
 * it calls Seal().
1790
 * This method should be called on a OGRFeatureDefn that has been sealed
1791
 * previously.
1792
 * GetTemporaryUnsealer() calls may be nested, in which case only the first
1793
 * one has an effect (similarly to a recursive mutex locked in a nested way
1794
 * from the same thread).
1795
 *
1796
 * This method should only be called by driver implementations.
1797
 *
1798
 * It is also possible to use the helper method whileUnsealing(). Example:
1799
 * whileUnsealing(poFeatureDefn)->some_method()
1800
 *
1801
 * @param bSealFields Whether fields and geometry fields should be unsealed and
1802
 *                    resealed.
1803
 *                    This is generally desirable, but in case of deferred
1804
 *                    resolution of them, this parameter should be set to false.
1805
 * @since GDAL 3.9
1806
 */
1807
OGRFeatureDefn::TemporaryUnsealer
1808
OGRFeatureDefn::GetTemporaryUnsealer(bool bSealFields)
1809
0
{
1810
0
    return TemporaryUnsealer(this, bSealFields);
1811
0
}
1812
1813
/*! @cond Doxygen_Suppress */
1814
1815
/************************************************************************/
1816
/*                TemporaryUnsealer::TemporaryUnsealer()                */
1817
/************************************************************************/
1818
1819
OGRFeatureDefn::TemporaryUnsealer::TemporaryUnsealer(
1820
    OGRFeatureDefn *poFeatureDefn, bool bSealFields)
1821
0
    : m_poFeatureDefn(poFeatureDefn), m_bSealFields(bSealFields)
1822
0
{
1823
0
    if (m_poFeatureDefn->m_nTemporaryUnsealCount == 0)
1824
0
    {
1825
0
        if (m_poFeatureDefn->m_bSealed)
1826
0
        {
1827
0
            m_poFeatureDefn->Unseal(m_bSealFields);
1828
0
            m_poFeatureDefn->m_nTemporaryUnsealCount = 1;
1829
0
        }
1830
0
        else
1831
0
        {
1832
0
            CPLError(CE_Warning, CPLE_AppDefined,
1833
0
                     "OGRFeatureDefn::GetTemporaryUnsealer() called on "
1834
0
                     "a unsealed object");
1835
0
            m_poFeatureDefn->m_nTemporaryUnsealCount = -1;
1836
0
        }
1837
0
    }
1838
0
    else if (m_poFeatureDefn->m_nTemporaryUnsealCount > 0)
1839
0
    {
1840
        // m_poFeatureDefn is already under an active TemporaryUnsealer.
1841
        // Just increment the counter
1842
0
        ++m_poFeatureDefn->m_nTemporaryUnsealCount;
1843
0
    }
1844
0
    else
1845
0
    {
1846
        // m_poFeatureDefn is already under a misused TemporaryUnsealer.
1847
        // Decrement again the counter
1848
0
        --m_poFeatureDefn->m_nTemporaryUnsealCount;
1849
0
    }
1850
0
}
1851
1852
/************************************************************************/
1853
/*               TemporaryUnsealer::~TemporaryUnsealer()                */
1854
/************************************************************************/
1855
1856
OGRFeatureDefn::TemporaryUnsealer::~TemporaryUnsealer()
1857
0
{
1858
0
    if (m_poFeatureDefn->m_nTemporaryUnsealCount > 0)
1859
0
    {
1860
        // m_poFeatureDefn is already under an active TemporaryUnsealer.
1861
        // Decrement increment the counter and unseal when it reaches 0
1862
0
        --m_poFeatureDefn->m_nTemporaryUnsealCount;
1863
0
        if (m_poFeatureDefn->m_nTemporaryUnsealCount == 0)
1864
0
        {
1865
0
            if (!m_poFeatureDefn->m_bSealed)
1866
0
            {
1867
0
                m_poFeatureDefn->Seal(m_bSealFields);
1868
0
            }
1869
0
            else
1870
0
            {
1871
0
                CPLError(
1872
0
                    CE_Failure, CPLE_AppDefined,
1873
0
                    "Misuse of sealing functionality. "
1874
0
                    "OGRFeatureDefn::TemporaryUnsealer::~TemporaryUnsealer() "
1875
0
                    "claled on a sealed object");
1876
0
            }
1877
0
        }
1878
0
    }
1879
0
    else
1880
0
    {
1881
        // m_poFeatureDefn is already under a misused TemporaryUnsealer.
1882
        // Increment the counter
1883
0
        CPLAssert(m_poFeatureDefn->m_nTemporaryUnsealCount < 0);
1884
0
        ++m_poFeatureDefn->m_nTemporaryUnsealCount;
1885
0
    }
1886
0
}
1887
1888
/*! @endcond */