Coverage Report

Created: 2025-11-16 06:25

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