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