Coverage Report

Created: 2025-06-13 06:29

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