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 2059770 : 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 2059770 : m_poStyleTable(nullptr), m_pszTmpFieldValue(nullptr)
75 : {
76 2059770 : const_cast<OGRFeatureDefn *>(poDefnIn)->Reference();
77 :
78 2059770 : const int nFieldCount = poDefn->GetFieldCount();
79 2059770 : pauFields = static_cast<OGRField *>(
80 2059770 : VSI_MALLOC_VERBOSE(nFieldCount * sizeof(OGRField)));
81 :
82 2059770 : papoGeometries = static_cast<OGRGeometry **>(
83 2059770 : VSI_CALLOC_VERBOSE(poDefn->GetGeomFieldCount(), sizeof(OGRGeometry *)));
84 :
85 : // Initialize array to the unset special value.
86 2059770 : if (pauFields != nullptr)
87 : {
88 12976500 : for (int i = 0; i < nFieldCount; i++)
89 : {
90 10916700 : pauFields[i].Set.nMarker1 = OGRUnsetMarker;
91 10916700 : pauFields[i].Set.nMarker2 = OGRUnsetMarker;
92 10916700 : pauFields[i].Set.nMarker3 = OGRUnsetMarker;
93 : }
94 : }
95 2059770 : }
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 128296 : OGRFeatureH OGR_F_Create(OGRFeatureDefnH hDefn)
118 :
119 : {
120 128296 : VALIDATE_POINTER1(hDefn, "OGR_F_Create", nullptr);
121 128296 : return OGRFeature::ToHandle(
122 256592 : OGRFeature::CreateFeature(OGRFeatureDefn::FromHandle(hDefn)));
123 : }
124 :
125 : /************************************************************************/
126 : /* ~OGRFeature() */
127 : /************************************************************************/
128 :
129 5613640 : OGRFeature::~OGRFeature()
130 :
131 : {
132 2059740 : if (pauFields != nullptr)
133 : {
134 : // We can call GetFieldCountUnsafe() as the constructor has called
135 : // the regular GetFieldCount()
136 2059740 : const int nFieldcount = poDefn->GetFieldCountUnsafe();
137 12977000 : for (int i = 0; i < nFieldcount; i++)
138 : {
139 10917200 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefnUnsafe(i);
140 :
141 10917200 : if (!IsFieldSetAndNotNullUnsafe(i))
142 3412380 : continue;
143 :
144 7504840 : switch (poFDefn->GetType())
145 : {
146 4061060 : case OFTString:
147 4061060 : if (pauFields[i].String != nullptr)
148 4060960 : VSIFree(pauFields[i].String);
149 4061060 : break;
150 :
151 58704 : case OFTBinary:
152 58704 : if (pauFields[i].Binary.paData != nullptr)
153 58702 : VSIFree(pauFields[i].Binary.paData);
154 58704 : break;
155 :
156 23768 : case OFTStringList:
157 23768 : CSLDestroy(pauFields[i].StringList.paList);
158 23768 : break;
159 :
160 81322 : case OFTIntegerList:
161 : case OFTInteger64List:
162 : case OFTRealList:
163 81322 : CPLFree(pauFields[i].IntegerList.paList);
164 81322 : break;
165 :
166 3279980 : default:
167 : // TODO(schwehr): Add support for wide strings.
168 3279980 : break;
169 : }
170 : }
171 : }
172 :
173 2059740 : if (papoGeometries != nullptr)
174 : {
175 2059740 : const int nGeomFieldCount = poDefn->GetGeomFieldCount();
176 :
177 3374900 : for (int i = 0; i < nGeomFieldCount; i++)
178 : {
179 1315160 : delete papoGeometries[i];
180 : }
181 : }
182 :
183 2059740 : if (poDefn)
184 2059740 : const_cast<OGRFeatureDefn *>(poDefn)->Release();
185 :
186 2059740 : CPLFree(pauFields);
187 2059740 : CPLFree(papoGeometries);
188 2059740 : CPLFree(m_pszStyleString);
189 2059740 : CPLFree(m_pszTmpFieldValue);
190 2059740 : CPLFree(m_pszNativeData);
191 2059740 : CPLFree(m_pszNativeMediaType);
192 3553900 : }
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 215355 : void OGR_F_Destroy(OGRFeatureH hFeat)
212 :
213 : {
214 215355 : delete OGRFeature::FromHandle(hFeat);
215 215355 : }
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 483735 : OGRFeature *OGRFeature::CreateFeature(const OGRFeatureDefn *poDefn)
238 :
239 : {
240 483735 : OGRFeature *poFeature = new (std::nothrow) OGRFeature(poDefn);
241 483735 : if (poFeature == nullptr)
242 0 : return nullptr;
243 :
244 0 : if ((poFeature->pauFields == nullptr &&
245 967470 : poDefn->GetFieldCountUnsafe() != 0) ||
246 483735 : (poFeature->papoGeometries == nullptr &&
247 0 : poDefn->GetGeomFieldCount() != 0))
248 : {
249 0 : delete poFeature;
250 0 : return nullptr;
251 : }
252 :
253 483735 : 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 66320 : void OGRFeature::DestroyFeature(OGRFeature *poFeature)
275 :
276 : {
277 66320 : delete poFeature;
278 66320 : }
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 3160 : void OGRFeature::Reset()
291 : {
292 3160 : nFID = OGRNullFID;
293 :
294 3160 : if (pauFields != nullptr)
295 : {
296 3160 : const int nFieldcount = poDefn->GetFieldCountUnsafe();
297 10381 : for (int i = 0; i < nFieldcount; i++)
298 : {
299 7221 : if (!IsFieldSetAndNotNullUnsafe(i))
300 1802 : continue;
301 :
302 5419 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefnUnsafe(i);
303 5419 : switch (poFDefn->GetType())
304 : {
305 452 : case OFTString:
306 452 : if (pauFields[i].String != nullptr)
307 452 : VSIFree(pauFields[i].String);
308 452 : 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 3976 : default:
326 : // TODO(schwehr): Add support for wide strings.
327 3976 : break;
328 : }
329 :
330 5419 : pauFields[i].Set.nMarker1 = OGRUnsetMarker;
331 5419 : pauFields[i].Set.nMarker2 = OGRUnsetMarker;
332 5419 : pauFields[i].Set.nMarker3 = OGRUnsetMarker;
333 : }
334 : }
335 :
336 3160 : if (papoGeometries != nullptr)
337 : {
338 3160 : const int nGeomFieldCount = poDefn->GetGeomFieldCount();
339 :
340 6194 : for (int i = 0; i < nGeomFieldCount; i++)
341 : {
342 3034 : delete papoGeometries[i];
343 3034 : papoGeometries[i] = nullptr;
344 : }
345 : }
346 :
347 3160 : if (m_pszStyleString)
348 : {
349 0 : CPLFree(m_pszStyleString);
350 0 : m_pszStyleString = nullptr;
351 : }
352 :
353 3160 : if (m_pszNativeData)
354 : {
355 0 : CPLFree(m_pszNativeData);
356 0 : m_pszNativeData = nullptr;
357 : }
358 :
359 3160 : if (m_pszNativeMediaType)
360 : {
361 0 : CPLFree(m_pszNativeMediaType);
362 0 : m_pszNativeMediaType = nullptr;
363 : }
364 3160 : }
365 :
366 : /************************************************************************/
367 : /* SetFDefnUnsafe() */
368 : /************************************************************************/
369 :
370 : //! @cond Doxygen_Suppress
371 26345 : void OGRFeature::SetFDefnUnsafe(OGRFeatureDefn *poNewFDefn)
372 : {
373 26345 : poNewFDefn->Reference();
374 26345 : const_cast<OGRFeatureDefn *>(poDefn)->Release();
375 26345 : poDefn = poNewFDefn;
376 26345 : }
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 48114 : OGRFeatureDefnH OGR_F_GetDefnRef(OGRFeatureH hFeat)
420 :
421 : {
422 48114 : VALIDATE_POINTER1(hFeat, "OGR_F_GetDefnRef", nullptr);
423 :
424 48114 : return OGRFeatureDefn::ToHandle(const_cast<OGRFeatureDefn *>(
425 96228 : 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 795171 : OGRErr OGRFeature::SetGeometryDirectly(OGRGeometry *poGeomIn)
456 :
457 : {
458 795171 : if (poGeomIn == GetGeometryRef())
459 : {
460 872 : return OGRERR_NONE;
461 : }
462 :
463 794299 : 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 39778 : OGRErr OGR_F_SetGeometryDirectly(OGRFeatureH hFeat, OGRGeometryH hGeom)
494 :
495 : {
496 39778 : VALIDATE_POINTER1(hFeat, "OGR_F_SetGeometryDirectly", OGRERR_FAILURE);
497 :
498 39778 : return OGRFeature::FromHandle(hFeat)->SetGeometryDirectly(
499 39778 : 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 237127 : OGRErr OGRFeature::SetGeometry(const OGRGeometry *poGeomIn)
530 :
531 : {
532 237127 : if (GetGeomFieldCount() < 1)
533 2 : return OGRERR_FAILURE;
534 :
535 237125 : 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 236704 : OGRErr OGR_F_SetGeometry(OGRFeatureH hFeat, OGRGeometryH hGeom)
565 :
566 : {
567 236704 : VALIDATE_POINTER1(hFeat, "OGR_F_SetGeometry", OGRERR_FAILURE);
568 :
569 473408 : return OGRFeature::FromHandle(hFeat)->SetGeometry(
570 473408 : 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 334614 : OGRErr OGRFeature::SetGeometry(std::unique_ptr<OGRGeometry> poGeomIn)
599 :
600 : {
601 334614 : 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 2670 : OGRGeometry *OGRFeature::StealGeometry()
622 :
623 : {
624 2670 : if (GetGeomFieldCount() > 0)
625 : {
626 2658 : OGRGeometry *poReturn = papoGeometries[0];
627 2658 : papoGeometries[0] = nullptr;
628 2658 : 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 10403 : OGRGeometry *OGRFeature::StealGeometry(int iGeomField)
650 :
651 : {
652 10403 : if (iGeomField >= 0 && iGeomField < GetGeomFieldCount())
653 : {
654 10402 : OGRGeometry *poReturn = papoGeometries[iGeomField];
655 10402 : papoGeometries[iGeomField] = nullptr;
656 10402 : 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 2074 : OGRGeometryH OGR_F_StealGeometry(OGRFeatureH hFeat)
681 :
682 : {
683 2074 : VALIDATE_POINTER1(hFeat, "OGR_F_StealGeometry", nullptr);
684 :
685 2074 : return OGRGeometry::ToHandle(
686 2074 : 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 2020120 : OGRGeometry *OGRFeature::GetGeometryRef()
738 :
739 : {
740 2020120 : if (GetGeomFieldCount() > 0)
741 2009070 : return GetGeomFieldRef(0);
742 :
743 11053 : 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 268123 : const OGRGeometry *OGRFeature::GetGeometryRef() const
759 :
760 : {
761 268123 : if (GetGeomFieldCount() > 0)
762 264734 : return GetGeomFieldRef(0);
763 :
764 3389 : 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 39876 : OGRGeometryH OGR_F_GetGeometryRef(OGRFeatureH hFeat)
784 :
785 : {
786 39876 : VALIDATE_POINTER1(hFeat, "OGR_F_GetGeometryRef", nullptr);
787 :
788 39876 : OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
789 39876 : OGRGeometry *poGeom = poFeature->GetGeometryRef();
790 :
791 39877 : 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 39876 : 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 3458050 : OGRGeometry *OGRFeature::GetGeomFieldRef(int iField)
822 :
823 : {
824 3458050 : if (iField < 0 || iField >= GetGeomFieldCount())
825 8 : return nullptr;
826 : else
827 3458040 : 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 289284 : const OGRGeometry *OGRFeature::GetGeomFieldRef(int iField) const
841 :
842 : {
843 289284 : if (iField < 0 || iField >= GetGeomFieldCount())
844 43 : return nullptr;
845 : else
846 289241 : 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 397 : OGRGeometryH OGR_F_GetGeomFieldRef(OGRFeatureH hFeat, int iField)
907 :
908 : {
909 397 : VALIDATE_POINTER1(hFeat, "OGR_F_GetGeomFieldRef", nullptr);
910 :
911 397 : OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
912 397 : OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iField);
913 :
914 398 : 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 397 : 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 36244 : OGRErr OGRFeature::SetGeomFieldDirectly(int iField, OGRGeometry *poGeomIn)
954 : {
955 36244 : if (poGeomIn && poGeomIn == GetGeomFieldRef(iField))
956 : {
957 0 : return OGRERR_NONE;
958 : }
959 :
960 36244 : 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 248620 : OGRErr OGRFeature::SetGeomField(int iField, const OGRGeometry *poGeomIn)
1022 :
1023 : {
1024 248620 : if (iField < 0 || iField >= GetGeomFieldCount())
1025 1 : return OGRERR_FAILURE;
1026 :
1027 248619 : if (papoGeometries[iField] != poGeomIn)
1028 : {
1029 247560 : delete papoGeometries[iField];
1030 :
1031 247560 : if (poGeomIn != nullptr)
1032 247383 : 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 248619 : 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 305 : OGRErr OGR_F_SetGeomField(OGRFeatureH hFeat, int iField, OGRGeometryH hGeom)
1065 :
1066 : {
1067 305 : VALIDATE_POINTER1(hFeat, "OGR_F_SetGeomField", OGRERR_FAILURE);
1068 :
1069 610 : return OGRFeature::FromHandle(hFeat)->SetGeomField(
1070 610 : 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 1175860 : OGRErr OGRFeature::SetGeomField(int iField,
1095 : std::unique_ptr<OGRGeometry> poGeomIn)
1096 :
1097 : {
1098 1175860 : if (iField < 0 || iField >= GetGeomFieldCount())
1099 : {
1100 5044 : return OGRERR_FAILURE;
1101 : }
1102 :
1103 1170820 : if (papoGeometries[iField] != poGeomIn.get())
1104 : {
1105 1170560 : delete papoGeometries[iField];
1106 1170560 : papoGeometries[iField] = poGeomIn.release();
1107 : }
1108 :
1109 1170820 : 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 346790 : OGRFeature *OGRFeature::Clone() const
1129 :
1130 : {
1131 346790 : OGRFeature *poNew = CreateFeature(poDefn);
1132 346790 : if (poNew == nullptr)
1133 0 : return nullptr;
1134 :
1135 346790 : if (!CopySelfTo(poNew))
1136 : {
1137 0 : delete poNew;
1138 0 : return nullptr;
1139 : }
1140 :
1141 346790 : 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 350486 : bool OGRFeature::CopySelfTo(OGRFeature *poNew) const
1183 : {
1184 350486 : const int nFieldCount = poDefn->GetFieldCountUnsafe();
1185 4583590 : for (int i = 0; i < nFieldCount; i++)
1186 : {
1187 4233100 : if (!poNew->SetFieldInternal(i, pauFields + i))
1188 : {
1189 0 : return false;
1190 : }
1191 : }
1192 350486 : if (poNew->papoGeometries)
1193 : {
1194 396633 : for (int i = 0; i < poDefn->GetGeomFieldCount(); i++)
1195 : {
1196 46147 : if (papoGeometries[i] != nullptr)
1197 : {
1198 42779 : poNew->papoGeometries[i] = papoGeometries[i]->clone();
1199 42779 : if (poNew->papoGeometries[i] == nullptr)
1200 : {
1201 0 : return false;
1202 : }
1203 : }
1204 : }
1205 : }
1206 :
1207 350486 : 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 350486 : poNew->SetFID(GetFID());
1217 :
1218 350486 : if (m_pszNativeData != nullptr)
1219 : {
1220 121 : poNew->m_pszNativeData = VSI_STRDUP_VERBOSE(m_pszNativeData);
1221 121 : if (poNew->m_pszNativeData == nullptr)
1222 : {
1223 0 : return false;
1224 : }
1225 : }
1226 :
1227 350486 : if (m_pszNativeMediaType != nullptr)
1228 : {
1229 121 : poNew->m_pszNativeMediaType = VSI_STRDUP_VERBOSE(m_pszNativeMediaType);
1230 121 : if (poNew->m_pszNativeMediaType == nullptr)
1231 : {
1232 0 : return false;
1233 : }
1234 : }
1235 :
1236 350486 : 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 113194 : int OGR_F_GetFieldCount(OGRFeatureH hFeat)
1271 :
1272 : {
1273 113194 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldCount", 0);
1274 :
1275 113194 : 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 189871 : OGRFieldDefnH OGR_F_GetFieldDefnRef(OGRFeatureH hFeat, int i)
1312 :
1313 : {
1314 189871 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldDefnRef", nullptr);
1315 :
1316 189871 : OGRFeature *poFeat = OGRFeature::FromHandle(hFeat);
1317 :
1318 189871 : return OGRFieldDefn::ToHandle(
1319 189871 : 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 3546 : int OGR_F_GetFieldIndex(OGRFeatureH hFeat, const char *pszName)
1358 :
1359 : {
1360 3546 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldIndex", 0);
1361 :
1362 3546 : 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 146 : int OGR_F_GetGeomFieldIndex(OGRFeatureH hFeat, const char *pszName)
1493 :
1494 : {
1495 146 : VALIDATE_POINTER1(hFeat, "OGR_F_GetGeomFieldIndex", 0);
1496 :
1497 146 : 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 406756 : int OGRFeature::IsFieldSet(int iField) const
1515 :
1516 : {
1517 406756 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
1518 406756 : 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 405696 : 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 103254 : int OGR_F_IsFieldSet(OGRFeatureH hFeat, int iField)
1566 :
1567 : {
1568 103254 : VALIDATE_POINTER1(hFeat, "OGR_F_IsFieldSet", 0);
1569 :
1570 103254 : const OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
1571 103254 : 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 103254 : 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 9541 : void OGRFeature::UnsetField(int iField)
1593 :
1594 : {
1595 9541 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
1596 :
1597 9541 : if (poFDefn == nullptr || !IsFieldSet(iField))
1598 9458 : 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 280435 : bool OGRFeature::IsFieldNull(int iField) const
1667 :
1668 : {
1669 280435 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
1670 280435 : 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 280435 : 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 102387 : int OGR_F_IsFieldNull(OGRFeatureH hFeat, int iField)
1699 :
1700 : {
1701 102387 : VALIDATE_POINTER1(hFeat, "OGR_F_IsFieldNull", 0);
1702 :
1703 102387 : const OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
1704 102387 : 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 102387 : 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 522516 : bool OGRFeature::IsFieldSetAndNotNull(int iField) const
1729 :
1730 : {
1731 522516 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
1732 522516 : if (iSpecialField >= 0)
1733 : {
1734 1060 : return CPL_TO_BOOL(IsFieldSet(iField));
1735 : }
1736 : else
1737 : {
1738 521456 : 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 2425 : int OGR_F_IsFieldSetAndNotNull(OGRFeatureH hFeat, int iField)
1760 :
1761 : {
1762 2425 : VALIDATE_POINTER1(hFeat, "OGR_F_IsFieldSetAndNotNull", 0);
1763 :
1764 2425 : OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
1765 :
1766 2425 : 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 2425 : 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 53582 : void OGRFeature::SetFieldNull(int iField)
1789 :
1790 : {
1791 53582 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
1792 :
1793 53582 : if (poFDefn == nullptr || IsFieldNull(iField))
1794 0 : return;
1795 :
1796 53582 : 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 53582 : 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 173681 : int OGRFeature::GetFieldAsInteger(int iField) const
1997 :
1998 : {
1999 173681 : int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
2000 173681 : 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 173662 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
2034 :
2035 173662 : if (poFDefn == nullptr)
2036 4 : return 0;
2037 :
2038 173658 : if (!IsFieldSetAndNotNullUnsafe(iField))
2039 14119 : return 0;
2040 :
2041 159539 : const OGRFieldType eType = poFDefn->GetType();
2042 159539 : if (eType == OFTInteger)
2043 : {
2044 130296 : return pauFields[iField].Integer;
2045 : }
2046 29243 : 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 29100 : else if (eType == OFTReal)
2065 : {
2066 22 : return static_cast<int>(pauFields[iField].Real);
2067 : }
2068 29078 : else if (eType == OFTString)
2069 : {
2070 29078 : if (pauFields[iField].String == nullptr)
2071 0 : return 0;
2072 : else
2073 29078 : 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 88592 : int OGR_F_GetFieldAsInteger(OGRFeatureH hFeat, int iField)
2099 :
2100 : {
2101 88592 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsInteger", 0);
2102 :
2103 88592 : 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 29591 : GIntBig OGRFeature::GetFieldAsInteger64(int iField) const
2140 :
2141 : {
2142 29591 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
2143 29591 : 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 28790 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
2163 :
2164 28790 : if (poFDefn == nullptr)
2165 0 : return 0;
2166 :
2167 28790 : if (!IsFieldSetAndNotNullUnsafe(iField))
2168 27 : return 0;
2169 :
2170 28763 : OGRFieldType eType = poFDefn->GetType();
2171 28763 : if (eType == OFTInteger)
2172 : {
2173 11751 : return static_cast<GIntBig>(pauFields[iField].Integer);
2174 : }
2175 17012 : else if (eType == OFTInteger64)
2176 : {
2177 16908 : 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 1506 : GIntBig OGR_F_GetFieldAsInteger64(OGRFeatureH hFeat, int iField)
2218 :
2219 : {
2220 1506 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsInteger64", 0);
2221 :
2222 1506 : 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 134272 : double OGRFeature::GetFieldAsDouble(int iField) const
2257 :
2258 : {
2259 134272 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
2260 134272 : 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 134247 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
2279 :
2280 134247 : if (poFDefn == nullptr)
2281 5 : return 0.0;
2282 :
2283 134242 : if (!IsFieldSetAndNotNullUnsafe(iField))
2284 96 : return 0.0;
2285 :
2286 134146 : const OGRFieldType eType = poFDefn->GetType();
2287 134146 : if (eType == OFTReal)
2288 : {
2289 69968 : 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 2590 : double OGR_F_GetFieldAsDouble(OGRFeatureH hFeat, int iField)
2330 :
2331 : {
2332 2590 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsDouble", 0);
2333 :
2334 2590 : return OGRFeature::FromHandle(hFeat)->GetFieldAsDouble(iField);
2335 : }
2336 :
2337 : /************************************************************************/
2338 : /* OGRFeatureFormatDateTimeBuffer() */
2339 : /************************************************************************/
2340 :
2341 1387 : 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 1387 : const int ms = OGR_GET_MS(fSecond);
2347 1387 : if (ms != 0)
2348 365 : 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 1022 : 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 1022 : snprintf(szTempBuffer, nMaxSize, "%04d/%02d/%02d %02d:%02d:%02d", nYear,
2362 : nMonth, nDay, nHour, nMinute, static_cast<int>(fSecond));
2363 : }
2364 :
2365 1387 : if (nTZFlag > 1)
2366 : {
2367 : char chSign;
2368 460 : const int nOffset = (nTZFlag - 100) * 15;
2369 460 : int nHours = static_cast<int>(nOffset / 60); // Round towards zero.
2370 460 : const int nMinutes = std::abs(nOffset - nHours * 60);
2371 :
2372 460 : if (nOffset < 0)
2373 : {
2374 63 : chSign = '-';
2375 63 : nHours = std::abs(nHours);
2376 : }
2377 : else
2378 : {
2379 397 : chSign = '+';
2380 : }
2381 :
2382 460 : if (nMinutes == 0)
2383 397 : snprintf(szTempBuffer + strlen(szTempBuffer),
2384 397 : 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 1387 : }
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 249571 : const char *OGRFeature::GetFieldAsString(int iField) const
2442 :
2443 : {
2444 249571 : CPLFree(m_pszTmpFieldValue);
2445 249571 : m_pszTmpFieldValue = nullptr;
2446 :
2447 249571 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
2448 249571 : 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 249298 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
2505 :
2506 249298 : if (poFDefn == nullptr)
2507 3 : return "";
2508 :
2509 249295 : if (!IsFieldSetAndNotNullUnsafe(iField))
2510 6178 : return "";
2511 :
2512 243117 : OGRFieldType eType = poFDefn->GetType();
2513 243117 : if (eType == OFTString)
2514 : {
2515 222836 : if (pauFields[iField].String == nullptr)
2516 0 : return "";
2517 : else
2518 222836 : return pauFields[iField].String;
2519 : }
2520 20281 : else if (eType == OFTInteger)
2521 : {
2522 7892 : constexpr size_t MAX_SIZE = 11 + 1;
2523 7892 : m_pszTmpFieldValue = static_cast<char *>(CPLMalloc(MAX_SIZE));
2524 7892 : snprintf(m_pszTmpFieldValue, MAX_SIZE, "%d", pauFields[iField].Integer);
2525 7892 : return m_pszTmpFieldValue;
2526 : }
2527 12389 : else if (eType == OFTInteger64)
2528 : {
2529 1050 : constexpr size_t MAX_SIZE = 20 + 1;
2530 1050 : m_pszTmpFieldValue = static_cast<char *>(CPLMalloc(MAX_SIZE));
2531 1050 : CPLsnprintf(m_pszTmpFieldValue, MAX_SIZE, CPL_FRMT_GIB,
2532 1050 : pauFields[iField].Integer64);
2533 1050 : return m_pszTmpFieldValue;
2534 : }
2535 11339 : else if (eType == OFTReal)
2536 : {
2537 2730 : char szFormat[32] = {};
2538 2730 : constexpr int TEMP_BUFFER_SIZE = 80;
2539 2730 : char szTempBuffer[TEMP_BUFFER_SIZE] = {};
2540 :
2541 2730 : if (poFDefn->GetWidth() != 0)
2542 : {
2543 727 : snprintf(szFormat, sizeof(szFormat), "%%.%df",
2544 : poFDefn->GetPrecision());
2545 :
2546 727 : CPLsnprintf(szTempBuffer, TEMP_BUFFER_SIZE, szFormat,
2547 727 : pauFields[iField].Real);
2548 : }
2549 : else
2550 : {
2551 2003 : 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 1982 : strcpy(szFormat, "%.15g");
2560 :
2561 1982 : CPLsnprintf(szTempBuffer, TEMP_BUFFER_SIZE, szFormat,
2562 1982 : pauFields[iField].Real);
2563 : }
2564 : }
2565 :
2566 2730 : m_pszTmpFieldValue = VSI_STRDUP_VERBOSE(szTempBuffer);
2567 2730 : if (m_pszTmpFieldValue == nullptr)
2568 0 : return "";
2569 2730 : return m_pszTmpFieldValue;
2570 : }
2571 8609 : else if (eType == OFTDateTime)
2572 : {
2573 : // "YYYY/MM/DD HH:MM:SS.sss+ZZ"
2574 1379 : constexpr size_t EXTRA_SPACE_FOR_NEGATIVE_OR_LARGE_YEARS = 5;
2575 1379 : constexpr size_t MAX_SIZE =
2576 : 26 + EXTRA_SPACE_FOR_NEGATIVE_OR_LARGE_YEARS + 1;
2577 1379 : m_pszTmpFieldValue = static_cast<char *>(CPLMalloc(MAX_SIZE));
2578 1379 : OGRFeatureFormatDateTimeBuffer(
2579 1379 : m_pszTmpFieldValue, MAX_SIZE, pauFields[iField].Date.Year,
2580 1379 : pauFields[iField].Date.Month, pauFields[iField].Date.Day,
2581 1379 : pauFields[iField].Date.Hour, pauFields[iField].Date.Minute,
2582 1379 : pauFields[iField].Date.Second, pauFields[iField].Date.TZFlag);
2583 :
2584 1379 : return m_pszTmpFieldValue;
2585 : }
2586 7230 : else if (eType == OFTDate)
2587 : {
2588 881 : constexpr size_t EXTRA_SPACE_FOR_NEGATIVE_OR_LARGE_YEARS = 5;
2589 881 : constexpr size_t MAX_SIZE =
2590 : 10 + EXTRA_SPACE_FOR_NEGATIVE_OR_LARGE_YEARS + 1;
2591 881 : m_pszTmpFieldValue = static_cast<char *>(CPLMalloc(MAX_SIZE));
2592 881 : snprintf(m_pszTmpFieldValue, MAX_SIZE, "%04d/%02d/%02d",
2593 881 : pauFields[iField].Date.Year, pauFields[iField].Date.Month,
2594 881 : pauFields[iField].Date.Day);
2595 881 : return m_pszTmpFieldValue;
2596 : }
2597 6349 : else if (eType == OFTTime)
2598 : {
2599 5271 : constexpr size_t EXTRA_SPACE_TO_MAKE_GCC_HAPPY = 2;
2600 5271 : constexpr size_t MAX_SIZE = 12 + EXTRA_SPACE_TO_MAKE_GCC_HAPPY + 1;
2601 5271 : m_pszTmpFieldValue = static_cast<char *>(CPLMalloc(MAX_SIZE));
2602 5271 : const int ms = OGR_GET_MS(pauFields[iField].Date.Second);
2603 5271 : 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 148 : snprintf(m_pszTmpFieldValue, MAX_SIZE, "%02d:%02d:%02d",
2609 148 : pauFields[iField].Date.Hour, pauFields[iField].Date.Minute,
2610 148 : static_cast<int>(pauFields[iField].Date.Second));
2611 :
2612 5271 : 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 12373 : const char *OGR_F_GetFieldAsString(OGRFeatureH hFeat, int iField)
2758 :
2759 : {
2760 12373 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsString", nullptr);
2761 :
2762 12373 : 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 64 : const char *OGRFeature::GetFieldAsISO8601DateTime(
2809 : int iField, CPL_UNUSED CSLConstList papszOptions) const
2810 :
2811 : {
2812 64 : CPLFree(m_pszTmpFieldValue);
2813 64 : m_pszTmpFieldValue = nullptr;
2814 :
2815 64 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
2816 64 : if (iSpecialField >= 0)
2817 : {
2818 0 : return "";
2819 : }
2820 :
2821 64 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
2822 :
2823 64 : if (poFDefn == nullptr)
2824 1 : return "";
2825 :
2826 63 : if (!IsFieldSetAndNotNullUnsafe(iField))
2827 1 : return "";
2828 :
2829 62 : OGRFieldType eType = poFDefn->GetType();
2830 62 : if (eType != OFTDateTime)
2831 1 : return "";
2832 :
2833 61 : m_pszTmpFieldValue =
2834 61 : static_cast<char *>(CPLMalloc(OGR_SIZEOF_ISO8601_DATETIME_BUFFER));
2835 61 : constexpr bool bAlwaysMillisecond = false;
2836 61 : OGRGetISO8601DateTime(&pauFields[iField], bAlwaysMillisecond,
2837 : m_pszTmpFieldValue);
2838 61 : return m_pszTmpFieldValue;
2839 : ;
2840 : }
2841 :
2842 : /************************************************************************/
2843 : /* OGR_F_GetFieldAsISO8601DateTime() */
2844 : /************************************************************************/
2845 :
2846 : /**
2847 : * \brief Fetch OFTDateTime field value as a ISO8601 representation.
2848 : *
2849 : * Return a string like "YYYY-MM6DDTHH:MM:SS(.sss)?(Z|([+|-]HH:MM))?"
2850 : * Milliseconds are omitted if equal to zero.
2851 : * Other field types, or errors will result in a return of an empty string.
2852 : *
2853 : * This function is the same as the C++ method OGRFeature::GetFieldAsISO8601DateTime().
2854 : *
2855 : * @param hFeat handle to the feature that owned the field.
2856 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
2857 : * @param papszOptions NULL terminated list of strings, or NULL.
2858 : * No options are defined currently.
2859 : *
2860 : * @return the field value. This string is internal, and should not be
2861 : * modified, or freed. Its lifetime may be very brief.
2862 : *
2863 : * @since GDAL 3.7
2864 : */
2865 :
2866 8 : const char *OGR_F_GetFieldAsISO8601DateTime(OGRFeatureH hFeat, int iField,
2867 : CSLConstList papszOptions)
2868 :
2869 : {
2870 8 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsISO8601DateTime", nullptr);
2871 :
2872 8 : return OGRFeature::FromHandle(hFeat)->GetFieldAsISO8601DateTime(
2873 8 : iField, papszOptions);
2874 : }
2875 :
2876 : /************************************************************************/
2877 : /* GetFieldAsIntegerList() */
2878 : /************************************************************************/
2879 :
2880 : /* clang-format off */
2881 : /**
2882 : * \fn OGRFeature::GetFieldAsIntegerList( const char* pszFName, int *pnCount ) const
2883 : * \brief Fetch field value as a list of integers.
2884 : *
2885 : * Currently this method only works for OFTIntegerList fields.
2886 :
2887 : * @param pszFName the name of the field to fetch.
2888 : * @param pnCount an integer to put the list count (number of integers) into.
2889 : *
2890 : * @return the field value. This list is internal, and should not be
2891 : * modified, or freed. Its lifetime may be very brief. If *pnCount is zero
2892 : * on return the returned pointer may be NULL or non-NULL.
2893 : * OFTReal and OFTInteger fields will be translated to string using
2894 : * sprintf(), but not necessarily using the established formatting rules.
2895 : * Other field types, or errors will result in a return value of zero.
2896 : */
2897 : /* clang-format on */
2898 :
2899 : /**
2900 : * \brief Fetch field value as a list of integers.
2901 : *
2902 : * Currently this method only works for OFTIntegerList fields.
2903 : *
2904 : * This method is the same as the C function OGR_F_GetFieldAsIntegerList().
2905 : *
2906 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
2907 : * @param pnCount an integer to put the list count (number of integers) into.
2908 : *
2909 : * @return the field value. This list is internal, and should not be
2910 : * modified, or freed. Its lifetime may be very brief. If *pnCount is zero
2911 : * on return the returned pointer may be NULL or non-NULL.
2912 : */
2913 :
2914 12624 : const int *OGRFeature::GetFieldAsIntegerList(int iField, int *pnCount) const
2915 :
2916 : {
2917 12624 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
2918 :
2919 25230 : if (poFDefn != nullptr && IsFieldSetAndNotNullUnsafe(iField) &&
2920 12606 : poFDefn->GetType() == OFTIntegerList)
2921 : {
2922 12606 : if (pnCount != nullptr)
2923 12606 : *pnCount = pauFields[iField].IntegerList.nCount;
2924 :
2925 12606 : return pauFields[iField].IntegerList.paList;
2926 : }
2927 :
2928 18 : if (pnCount != nullptr)
2929 18 : *pnCount = 0;
2930 :
2931 18 : return nullptr;
2932 : }
2933 :
2934 : /************************************************************************/
2935 : /* OGR_F_GetFieldAsIntegerList() */
2936 : /************************************************************************/
2937 :
2938 : /**
2939 : * \brief Fetch field value as a list of integers.
2940 : *
2941 : * Currently this function only works for OFTIntegerList fields.
2942 : *
2943 : * This function is the same as the C++ method
2944 : * OGRFeature::GetFieldAsIntegerList().
2945 : *
2946 : * @param hFeat handle to the feature that owned the field.
2947 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
2948 : * @param pnCount an integer to put the list count (number of integers) into.
2949 : *
2950 : * @return the field value. This list is internal, and should not be
2951 : * modified, or freed. Its lifetime may be very brief. If *pnCount is zero
2952 : * on return the returned pointer may be NULL or non-NULL.
2953 : */
2954 :
2955 813 : const int *OGR_F_GetFieldAsIntegerList(OGRFeatureH hFeat, int iField,
2956 : int *pnCount)
2957 :
2958 : {
2959 813 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsIntegerList", nullptr);
2960 :
2961 813 : return OGRFeature::FromHandle(hFeat)->GetFieldAsIntegerList(iField,
2962 813 : pnCount);
2963 : }
2964 :
2965 : /************************************************************************/
2966 : /* GetFieldAsInteger64List() */
2967 : /************************************************************************/
2968 :
2969 : /* clang-format off */
2970 : /**
2971 : * \fn OGRFeature::GetFieldAsInteger64List( const char* pszFName, int *pnCount ) const
2972 : * \brief Fetch field value as a list of 64 bit integers.
2973 : *
2974 : * Currently this method only works for OFTInteger64List fields.
2975 :
2976 : * @param pszFName the name of the field to fetch.
2977 : * @param pnCount an integer to put the list count (number of integers) into.
2978 : *
2979 : * @return the field value. This list is internal, and should not be
2980 : * modified, or freed. Its lifetime may be very brief. If *pnCount is zero
2981 : * on return the returned pointer may be NULL or non-NULL.
2982 : */
2983 : /* clang-format on */
2984 :
2985 : /**
2986 : * \brief Fetch field value as a list of 64 bit integers.
2987 : *
2988 : * Currently this method only works for OFTInteger64List fields.
2989 : *
2990 : * This method is the same as the C function OGR_F_GetFieldAsInteger64List().
2991 : *
2992 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
2993 : * @param pnCount an integer to put the list count (number of integers) into.
2994 : *
2995 : * @return the field value. This list is internal, and should not be
2996 : * modified, or freed. Its lifetime may be very brief. If *pnCount is zero
2997 : * on return the returned pointer may be NULL or non-NULL.
2998 : */
2999 :
3000 10902 : const GIntBig *OGRFeature::GetFieldAsInteger64List(int iField,
3001 : int *pnCount) const
3002 :
3003 : {
3004 10902 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3005 :
3006 21804 : if (poFDefn != nullptr && IsFieldSetAndNotNullUnsafe(iField) &&
3007 10902 : poFDefn->GetType() == OFTInteger64List)
3008 : {
3009 10902 : if (pnCount != nullptr)
3010 10902 : *pnCount = pauFields[iField].Integer64List.nCount;
3011 :
3012 10902 : return pauFields[iField].Integer64List.paList;
3013 : }
3014 :
3015 0 : if (pnCount != nullptr)
3016 0 : *pnCount = 0;
3017 :
3018 0 : return nullptr;
3019 : }
3020 :
3021 : /************************************************************************/
3022 : /* OGR_F_GetFieldAsInteger64List() */
3023 : /************************************************************************/
3024 :
3025 : /**
3026 : * \brief Fetch field value as a list of 64 bit integers.
3027 : *
3028 : * Currently this function only works for OFTInteger64List fields.
3029 : *
3030 : * This function is the same as the C++ method
3031 : * OGRFeature::GetFieldAsInteger64List().
3032 : *
3033 : * @param hFeat handle to the feature that owned the field.
3034 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3035 : * @param pnCount an integer to put the list count (number of integers) into.
3036 : *
3037 : * @return the field value. This list is internal, and should not be
3038 : * modified, or freed. Its lifetime may be very brief. If *pnCount is zero
3039 : * on return the returned pointer may be NULL or non-NULL.
3040 : */
3041 :
3042 333 : const GIntBig *OGR_F_GetFieldAsInteger64List(OGRFeatureH hFeat, int iField,
3043 : int *pnCount)
3044 :
3045 : {
3046 333 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsInteger64List", nullptr);
3047 :
3048 333 : return OGRFeature::FromHandle(hFeat)->GetFieldAsInteger64List(iField,
3049 333 : pnCount);
3050 : }
3051 :
3052 : /************************************************************************/
3053 : /* GetFieldAsDoubleList() */
3054 : /************************************************************************/
3055 :
3056 : /* clang-format off */
3057 : /**
3058 : * \fn OGRFeature::GetFieldAsDoubleList( const char* pszFName, int *pnCount ) const
3059 : * \brief Fetch field value as a list of doubles.
3060 : *
3061 : * Currently this method only works for OFTRealList fields.
3062 :
3063 : * @param pszFName the name of the field to fetch.
3064 : * @param pnCount an integer to put the list count (number of doubles) into.
3065 : *
3066 : * @return the field value. This list is internal, and should not be
3067 : * modified, or freed. Its lifetime may be very brief. If *pnCount is zero
3068 : * on return the returned pointer may be NULL or non-NULL.
3069 : */
3070 : /* clang-format on */
3071 :
3072 : /**
3073 : * \brief Fetch field value as a list of doubles.
3074 : *
3075 : * Currently this method only works for OFTRealList fields.
3076 : *
3077 : * This method is the same as the C function OGR_F_GetFieldAsDoubleList().
3078 : *
3079 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3080 : * @param pnCount an integer to put the list count (number of doubles) into.
3081 : *
3082 : * @return the field value. This list is internal, and should not be
3083 : * modified, or freed. Its lifetime may be very brief. If *pnCount is zero
3084 : * on return the returned pointer may be NULL or non-NULL.
3085 : */
3086 :
3087 6777 : const double *OGRFeature::GetFieldAsDoubleList(int iField, int *pnCount) const
3088 :
3089 : {
3090 6777 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3091 :
3092 8522 : if (poFDefn != nullptr && IsFieldSetAndNotNullUnsafe(iField) &&
3093 1745 : poFDefn->GetType() == OFTRealList)
3094 : {
3095 1745 : if (pnCount != nullptr)
3096 1745 : *pnCount = pauFields[iField].RealList.nCount;
3097 :
3098 1745 : return pauFields[iField].RealList.paList;
3099 : }
3100 :
3101 5032 : if (pnCount != nullptr)
3102 5032 : *pnCount = 0;
3103 :
3104 5032 : return nullptr;
3105 : }
3106 :
3107 : /************************************************************************/
3108 : /* OGR_F_GetFieldAsDoubleList() */
3109 : /************************************************************************/
3110 :
3111 : /**
3112 : * \brief Fetch field value as a list of doubles.
3113 : *
3114 : * Currently this function only works for OFTRealList fields.
3115 : *
3116 : * This function is the same as the C++ method
3117 : * OGRFeature::GetFieldAsDoubleList().
3118 : *
3119 : * @param hFeat handle to the feature that owned the field.
3120 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3121 : * @param pnCount an integer to put the list count (number of doubles) into.
3122 : *
3123 : * @return the field value. This list is internal, and should not be
3124 : * modified, or freed. Its lifetime may be very brief. If *pnCount is zero
3125 : * on return the returned pointer may be NULL or non-NULL.
3126 : */
3127 :
3128 678 : const double *OGR_F_GetFieldAsDoubleList(OGRFeatureH hFeat, int iField,
3129 : int *pnCount)
3130 :
3131 : {
3132 678 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsDoubleList", nullptr);
3133 :
3134 678 : return OGRFeature::FromHandle(hFeat)->GetFieldAsDoubleList(iField, pnCount);
3135 : }
3136 :
3137 : /************************************************************************/
3138 : /* GetFieldAsStringList() */
3139 : /************************************************************************/
3140 : /**
3141 : * \fn OGRFeature::GetFieldAsStringList( const char* pszFName ) const
3142 : * \brief Fetch field value as a list of strings.
3143 : *
3144 : * Currently this method only works for OFTStringList fields.
3145 : *
3146 : * The returned list is terminated by a NULL pointer. The number of
3147 : * elements can also be calculated using CSLCount().
3148 : *
3149 : * @param pszFName the name of the field to fetch.
3150 : *
3151 : * @return the field value. This list is internal, and should not be
3152 : * modified, or freed. Its lifetime may be very brief.
3153 : */
3154 :
3155 : /**
3156 : * \brief Fetch field value as a list of strings.
3157 : *
3158 : * Currently this method only works for OFTStringList fields.
3159 : *
3160 : * The returned list is terminated by a NULL pointer. The number of
3161 : * elements can also be calculated using CSLCount().
3162 : *
3163 : * This method is the same as the C function OGR_F_GetFieldAsStringList().
3164 : *
3165 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3166 : *
3167 : * @return the field value. This list is internal, and should not be
3168 : * modified, or freed. Its lifetime may be very brief.
3169 : */
3170 :
3171 11370 : char **OGRFeature::GetFieldAsStringList(int iField) const
3172 :
3173 : {
3174 11370 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3175 :
3176 11370 : if (poFDefn == nullptr)
3177 0 : return nullptr;
3178 :
3179 11370 : if (!IsFieldSetAndNotNullUnsafe(iField))
3180 92 : return nullptr;
3181 :
3182 11278 : if (poFDefn->GetType() == OFTStringList)
3183 : {
3184 11278 : return pauFields[iField].StringList.paList;
3185 : }
3186 :
3187 0 : return nullptr;
3188 : }
3189 :
3190 : /************************************************************************/
3191 : /* OGR_F_GetFieldAsStringList() */
3192 : /************************************************************************/
3193 :
3194 : /**
3195 : * \brief Fetch field value as a list of strings.
3196 : *
3197 : * Currently this method only works for OFTStringList fields.
3198 : *
3199 : * The returned list is terminated by a NULL pointer. The number of
3200 : * elements can also be calculated using CSLCount().
3201 : *
3202 : * This function is the same as the C++ method
3203 : * OGRFeature::GetFieldAsStringList().
3204 : *
3205 : * @param hFeat handle to the feature that owned the field.
3206 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3207 : *
3208 : * @return the field value. This list is internal, and should not be
3209 : * modified, or freed. Its lifetime may be very brief.
3210 : */
3211 :
3212 347 : char **OGR_F_GetFieldAsStringList(OGRFeatureH hFeat, int iField)
3213 :
3214 : {
3215 347 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsStringList", nullptr);
3216 :
3217 347 : return OGRFeature::FromHandle(hFeat)->GetFieldAsStringList(iField);
3218 : }
3219 :
3220 : /************************************************************************/
3221 : /* GetFieldAsBinary() */
3222 : /************************************************************************/
3223 :
3224 : /**
3225 : * \brief Fetch field value as binary data.
3226 : *
3227 : * This method only works for OFTBinary and OFTString fields.
3228 : *
3229 : * This method is the same as the C function OGR_F_GetFieldAsBinary().
3230 : *
3231 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3232 : * @param pnBytes location to put the number of bytes returned.
3233 : *
3234 : * @return the field value. This data is internal, and should not be
3235 : * modified, or freed. Its lifetime may be very brief.
3236 : */
3237 :
3238 29605 : GByte *OGRFeature::GetFieldAsBinary(int iField, int *pnBytes) const
3239 :
3240 : {
3241 29605 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3242 :
3243 29605 : *pnBytes = 0;
3244 :
3245 29605 : if (poFDefn == nullptr)
3246 0 : return nullptr;
3247 :
3248 29605 : if (!IsFieldSetAndNotNullUnsafe(iField))
3249 6 : return nullptr;
3250 :
3251 29599 : if (poFDefn->GetType() == OFTBinary)
3252 : {
3253 29599 : *pnBytes = pauFields[iField].Binary.nCount;
3254 29599 : return pauFields[iField].Binary.paData;
3255 : }
3256 0 : else if (poFDefn->GetType() == OFTString)
3257 : {
3258 0 : *pnBytes = static_cast<int>(strlen(pauFields[iField].String));
3259 0 : return reinterpret_cast<GByte *>(pauFields[iField].String);
3260 : }
3261 :
3262 0 : return nullptr;
3263 : }
3264 :
3265 : /************************************************************************/
3266 : /* OGR_F_GetFieldAsBinary() */
3267 : /************************************************************************/
3268 :
3269 : /**
3270 : * \brief Fetch field value as binary.
3271 : *
3272 : * This method only works for OFTBinary and OFTString fields.
3273 : *
3274 : * This function is the same as the C++ method
3275 : * OGRFeature::GetFieldAsBinary().
3276 : *
3277 : * @param hFeat handle to the feature that owned the field.
3278 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3279 : * @param pnBytes location to place count of bytes returned.
3280 : *
3281 : * @return the field value. This list is internal, and should not be
3282 : * modified, or freed. Its lifetime may be very brief.
3283 : */
3284 :
3285 315 : GByte *OGR_F_GetFieldAsBinary(OGRFeatureH hFeat, int iField, int *pnBytes)
3286 :
3287 : {
3288 315 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsBinary", nullptr);
3289 315 : VALIDATE_POINTER1(pnBytes, "OGR_F_GetFieldAsBinary", nullptr);
3290 :
3291 315 : return OGRFeature::FromHandle(hFeat)->GetFieldAsBinary(iField, pnBytes);
3292 : }
3293 :
3294 : /************************************************************************/
3295 : /* GetFieldAsDateTime() */
3296 : /************************************************************************/
3297 :
3298 : /**
3299 : * \brief Fetch field value as date and time.
3300 : *
3301 : * Currently this method only works for OFTDate, OFTTime and OFTDateTime fields.
3302 : *
3303 : * This method is the same as the C function OGR_F_GetFieldAsDateTime().
3304 : *
3305 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3306 : * @param pnYear (including century)
3307 : * @param pnMonth (1-12)
3308 : * @param pnDay (1-31)
3309 : * @param pnHour (0-23)
3310 : * @param pnMinute (0-59)
3311 : * @param pfSecond (0-59 with millisecond accuracy)
3312 : * @param pnTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
3313 : *
3314 : * @return TRUE on success or FALSE on failure.
3315 : */
3316 :
3317 14229 : int OGRFeature::GetFieldAsDateTime(int iField, int *pnYear, int *pnMonth,
3318 : int *pnDay, int *pnHour, int *pnMinute,
3319 : float *pfSecond, int *pnTZFlag) const
3320 :
3321 : {
3322 14229 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3323 :
3324 14229 : if (poFDefn == nullptr)
3325 0 : return FALSE;
3326 :
3327 14229 : if (!IsFieldSetAndNotNullUnsafe(iField))
3328 1 : return FALSE;
3329 :
3330 16986 : if (poFDefn->GetType() == OFTDate || poFDefn->GetType() == OFTTime ||
3331 2758 : poFDefn->GetType() == OFTDateTime)
3332 : {
3333 14228 : if (pnYear)
3334 14220 : *pnYear = pauFields[iField].Date.Year;
3335 14228 : if (pnMonth)
3336 14167 : *pnMonth = pauFields[iField].Date.Month;
3337 14228 : if (pnDay)
3338 14167 : *pnDay = pauFields[iField].Date.Day;
3339 14228 : if (pnHour)
3340 14167 : *pnHour = pauFields[iField].Date.Hour;
3341 14228 : if (pnMinute)
3342 14167 : *pnMinute = pauFields[iField].Date.Minute;
3343 14228 : if (pfSecond)
3344 14167 : *pfSecond = pauFields[iField].Date.Second;
3345 14228 : if (pnTZFlag)
3346 14159 : *pnTZFlag = pauFields[iField].Date.TZFlag;
3347 :
3348 14228 : return TRUE;
3349 : }
3350 :
3351 0 : return FALSE;
3352 : }
3353 :
3354 : /**
3355 : * \brief Fetch field value as date and time.
3356 : *
3357 : * Currently this method only works for OFTDate, OFTTime and OFTDateTime fields.
3358 : *
3359 : * This method is the same as the C function OGR_F_GetFieldAsDateTime().
3360 : *
3361 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3362 : * @param pnYear (including century)
3363 : * @param pnMonth (1-12)
3364 : * @param pnDay (1-31)
3365 : * @param pnHour (0-23)
3366 : * @param pnMinute (0-59)
3367 : * @param pnSecond (0-59)
3368 : * @param pnTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
3369 : *
3370 : * @return TRUE on success or FALSE on failure.
3371 : */
3372 :
3373 5202 : int OGRFeature::GetFieldAsDateTime(int iField, int *pnYear, int *pnMonth,
3374 : int *pnDay, int *pnHour, int *pnMinute,
3375 : int *pnSecond, int *pnTZFlag) const
3376 : {
3377 5202 : float fSecond = 0.0f;
3378 5202 : const bool bRet = CPL_TO_BOOL(GetFieldAsDateTime(
3379 : iField, pnYear, pnMonth, pnDay, pnHour, pnMinute, &fSecond, pnTZFlag));
3380 5202 : if (bRet && pnSecond)
3381 5202 : *pnSecond = static_cast<int>(fSecond);
3382 5202 : return bRet;
3383 : }
3384 :
3385 : /************************************************************************/
3386 : /* OGR_F_GetFieldAsDateTime() */
3387 : /************************************************************************/
3388 :
3389 : /**
3390 : * \brief Fetch field value as date and time.
3391 : *
3392 : * Currently this method only works for OFTDate, OFTTime and OFTDateTime fields.
3393 : *
3394 : * This function is the same as the C++ method
3395 : * OGRFeature::GetFieldAsDateTime().
3396 : *
3397 : * @param hFeat handle to the feature that owned the field.
3398 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3399 : * @param pnYear (including century)
3400 : * @param pnMonth (1-12)
3401 : * @param pnDay (1-31)
3402 : * @param pnHour (0-23)
3403 : * @param pnMinute (0-59)
3404 : * @param pnSecond (0-59)
3405 : * @param pnTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
3406 : *
3407 : * @return TRUE on success or FALSE on failure.
3408 : *
3409 : * @see Use OGR_F_GetFieldAsDateTimeEx() for second with millisecond accuracy.
3410 : */
3411 :
3412 0 : int OGR_F_GetFieldAsDateTime(OGRFeatureH hFeat, int iField, int *pnYear,
3413 : int *pnMonth, int *pnDay, int *pnHour,
3414 : int *pnMinute, int *pnSecond, int *pnTZFlag)
3415 :
3416 : {
3417 0 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsDateTime", 0);
3418 :
3419 0 : float fSecond = 0.0f;
3420 : const bool bRet =
3421 0 : CPL_TO_BOOL(OGRFeature::FromHandle(hFeat)->GetFieldAsDateTime(
3422 : iField, pnYear, pnMonth, pnDay, pnHour, pnMinute, &fSecond,
3423 : pnTZFlag));
3424 0 : if (bRet && pnSecond)
3425 0 : *pnSecond = static_cast<int>(fSecond);
3426 0 : return bRet;
3427 : }
3428 :
3429 : /************************************************************************/
3430 : /* OGR_F_GetFieldAsDateTimeEx() */
3431 : /************************************************************************/
3432 :
3433 : /**
3434 : * \brief Fetch field value as date and time.
3435 : *
3436 : * Currently this method only works for OFTDate, OFTTime and OFTDateTime fields.
3437 : *
3438 : * This function is the same as the C++ method
3439 : * OGRFeature::GetFieldAsDateTime().
3440 : *
3441 : * @param hFeat handle to the feature that owned the field.
3442 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3443 : * @param pnYear (including century)
3444 : * @param pnMonth (1-12)
3445 : * @param pnDay (1-31)
3446 : * @param pnHour (0-23)
3447 : * @param pnMinute (0-59)
3448 : * @param pfSecond (0-59 with millisecond accuracy)
3449 : * @param pnTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
3450 : *
3451 : * @return TRUE on success or FALSE on failure.
3452 : */
3453 :
3454 87 : int OGR_F_GetFieldAsDateTimeEx(OGRFeatureH hFeat, int iField, int *pnYear,
3455 : int *pnMonth, int *pnDay, int *pnHour,
3456 : int *pnMinute, float *pfSecond, int *pnTZFlag)
3457 :
3458 : {
3459 87 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsDateTimeEx", 0);
3460 :
3461 87 : return OGRFeature::FromHandle(hFeat)->GetFieldAsDateTime(
3462 87 : iField, pnYear, pnMonth, pnDay, pnHour, pnMinute, pfSecond, pnTZFlag);
3463 : }
3464 :
3465 : /************************************************************************/
3466 : /* OGRFeatureGetIntegerValue() */
3467 : /************************************************************************/
3468 :
3469 1728670 : static int OGRFeatureGetIntegerValue(const OGRFeatureDefn *poDefn,
3470 : const OGRFieldDefn *poFDefn, int nValue)
3471 : {
3472 1728670 : if (poFDefn->GetSubType() == OFSTBoolean && nValue != 0 && nValue != 1)
3473 : {
3474 8 : CPLError(CE_Warning, CPLE_AppDefined,
3475 : "Field %s.%s: Only 0 or 1 should be passed for a OFSTBoolean "
3476 : "subtype. Considering non-zero value %d as 1.",
3477 4 : poDefn->GetName(), poFDefn->GetNameRef(), nValue);
3478 4 : nValue = 1;
3479 : }
3480 1728660 : else if (poFDefn->GetSubType() == OFSTInt16)
3481 : {
3482 6190 : if (nValue < -32768)
3483 : {
3484 2 : CPLError(CE_Warning, CPLE_AppDefined,
3485 : "Field %s.%s: Out-of-range value for a OFSTInt16 subtype. "
3486 : "Considering value %d as -32768.",
3487 1 : poDefn->GetName(), poFDefn->GetNameRef(), nValue);
3488 1 : nValue = -32768;
3489 : }
3490 6189 : else if (nValue > 32767)
3491 : {
3492 2 : CPLError(CE_Warning, CPLE_AppDefined,
3493 : "Field %s.%s: Out-of-range value for a OFSTInt16 subtype. "
3494 : "Considering value %d as 32767.",
3495 1 : poDefn->GetName(), poFDefn->GetNameRef(), nValue);
3496 1 : nValue = 32767;
3497 : }
3498 : }
3499 1728670 : return nValue;
3500 : }
3501 :
3502 : /************************************************************************/
3503 : /* GetFieldAsSerializedJSon() */
3504 : /************************************************************************/
3505 :
3506 : /**
3507 : * \brief Fetch field value as a serialized JSon object.
3508 : *
3509 : * Currently this method only works for OFTString with OFSTJSON subtype,
3510 : * OFTStringList, OFTIntegerList,
3511 : * OFTInteger64List and OFTRealList
3512 : *
3513 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3514 : *
3515 : * @return a string that must be de-allocate with CPLFree()
3516 : */
3517 15100 : char *OGRFeature::GetFieldAsSerializedJSon(int iField) const
3518 :
3519 : {
3520 15100 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
3521 15100 : if (iSpecialField >= 0)
3522 : {
3523 0 : return nullptr;
3524 : }
3525 :
3526 15100 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3527 :
3528 15100 : if (poFDefn == nullptr)
3529 0 : return nullptr;
3530 :
3531 15100 : if (!IsFieldSetAndNotNullUnsafe(iField))
3532 0 : return nullptr;
3533 :
3534 15100 : char *pszRet = nullptr;
3535 15100 : OGRFieldType eType = poFDefn->GetType();
3536 15100 : if (eType == OFTString && poFDefn->GetSubType() == OFSTJSON)
3537 : {
3538 18 : if (pauFields[iField].String[0] != '[' &&
3539 6 : pauFields[iField].String[0] != '{' &&
3540 3 : strcmp(pauFields[iField].String, "true") != 0 &&
3541 14 : strcmp(pauFields[iField].String, "false") != 0 &&
3542 2 : CPLGetValueType(pauFields[iField].String) == CPL_VALUE_STRING)
3543 : {
3544 1 : pszRet = CPLStrdup(('"' +
3545 2 : CPLString(pauFields[iField].String)
3546 2 : .replaceAll('\\', "\\\\")
3547 2 : .replaceAll('"', "\\\"") +
3548 : '"')
3549 : .c_str());
3550 : }
3551 : else
3552 : {
3553 5 : pszRet = CPLStrdup(pauFields[iField].String);
3554 : }
3555 : }
3556 15094 : else if (eType == OFTStringList)
3557 : {
3558 5032 : char **papszValues = GetFieldAsStringList(iField);
3559 5032 : if (papszValues == nullptr)
3560 : {
3561 1 : pszRet = CPLStrdup("[]");
3562 : }
3563 : else
3564 : {
3565 5031 : json_object *poObj = json_object_new_array();
3566 15094 : for (int i = 0; papszValues[i] != nullptr; i++)
3567 : {
3568 10063 : json_object_array_add(poObj,
3569 10063 : json_object_new_string(papszValues[i]));
3570 : }
3571 5031 : pszRet = CPLStrdup(json_object_to_json_string(poObj));
3572 5031 : json_object_put(poObj);
3573 : }
3574 : }
3575 10062 : else if (eType == OFTIntegerList)
3576 : {
3577 5030 : json_object *poObj = json_object_new_array();
3578 5030 : int nCount = 0;
3579 5030 : const int *panValues = GetFieldAsIntegerList(iField, &nCount);
3580 5030 : if (poFDefn->GetSubType() == OFSTBoolean)
3581 : {
3582 21 : for (int i = 0; i < nCount; i++)
3583 : {
3584 14 : json_object_array_add(
3585 14 : poObj, json_object_new_boolean(panValues[i] != 0));
3586 : }
3587 : }
3588 : else
3589 : {
3590 10073 : for (int i = 0; i < nCount; i++)
3591 : {
3592 5050 : json_object_array_add(poObj, json_object_new_int(panValues[i]));
3593 : }
3594 : }
3595 5030 : pszRet = CPLStrdup(json_object_to_json_string(poObj));
3596 5030 : json_object_put(poObj);
3597 : }
3598 5032 : else if (eType == OFTInteger64List)
3599 : {
3600 5014 : json_object *poObj = json_object_new_array();
3601 5014 : int nCount = 0;
3602 5014 : const GIntBig *panValues = GetFieldAsInteger64List(iField, &nCount);
3603 10041 : for (int i = 0; i < nCount; i++)
3604 : {
3605 5027 : json_object_array_add(poObj, json_object_new_int64(panValues[i]));
3606 : }
3607 5014 : pszRet = CPLStrdup(json_object_to_json_string(poObj));
3608 5014 : json_object_put(poObj);
3609 : }
3610 18 : else if (eType == OFTRealList)
3611 : {
3612 18 : json_object *poObj = json_object_new_array();
3613 18 : int nCount = 0;
3614 18 : const double *padfValues = GetFieldAsDoubleList(iField, &nCount);
3615 54 : for (int i = 0; i < nCount; i++)
3616 : {
3617 36 : json_object_array_add(poObj, json_object_new_double(padfValues[i]));
3618 : }
3619 18 : pszRet = CPLStrdup(json_object_to_json_string(poObj));
3620 18 : json_object_put(poObj);
3621 : }
3622 :
3623 15100 : return pszRet;
3624 : }
3625 :
3626 : /************************************************************************/
3627 : /* SetField() */
3628 : /************************************************************************/
3629 :
3630 : /**
3631 : * \fn OGRFeature::SetField( const char* pszFName, int nValue )
3632 : * \brief Set field to integer value.
3633 : * OFTInteger, OFTInteger64 and OFTReal fields will be set directly. OFTString
3634 : * fields will be assigned a string representation of the value, but not
3635 : * necessarily taking into account formatting constraints on this field. Other
3636 : * field types may be unaffected.
3637 : *
3638 : * @note This method has only an effect on the in-memory feature object. If
3639 : * this object comes from a layer and the modifications must be serialized back
3640 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
3641 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
3642 : *
3643 : * @param pszFName the name of the field to set.
3644 : * @param nValue the value to assign.
3645 : */
3646 :
3647 : /**
3648 : * \brief Set field to integer value.
3649 : *
3650 : * OFTInteger, OFTInteger64 and OFTReal fields will be set directly. OFTString
3651 : * fields will be assigned a string representation of the value, but not
3652 : * necessarily taking into account formatting constraints on this field. Other
3653 : * field types may be unaffected.
3654 : *
3655 : * This method is the same as the C function OGR_F_SetFieldInteger().
3656 : *
3657 : * @note This method has only an effect on the in-memory feature object. If
3658 : * this object comes from a layer and the modifications must be serialized back
3659 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
3660 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
3661 : *
3662 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3663 : * @param nValue the value to assign.
3664 : */
3665 :
3666 1656810 : void OGRFeature::SetField(int iField, int nValue)
3667 :
3668 : {
3669 1656810 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3670 :
3671 1656810 : if (poFDefn == nullptr)
3672 0 : return;
3673 :
3674 1656810 : OGRFieldType eType = poFDefn->GetType();
3675 1656810 : if (eType == OFTInteger)
3676 : {
3677 3307460 : pauFields[iField].Integer =
3678 1653730 : OGRFeatureGetIntegerValue(poDefn, poFDefn, nValue);
3679 1653730 : pauFields[iField].Set.nMarker2 = 0;
3680 1653730 : pauFields[iField].Set.nMarker3 = 0;
3681 : }
3682 3077 : else if (eType == OFTInteger64)
3683 : {
3684 1194 : pauFields[iField].Integer64 =
3685 1194 : OGRFeatureGetIntegerValue(poDefn, poFDefn, nValue);
3686 : }
3687 1883 : else if (eType == OFTReal)
3688 : {
3689 1781 : pauFields[iField].Real = nValue;
3690 : }
3691 102 : else if (eType == OFTIntegerList)
3692 : {
3693 9 : SetField(iField, 1, &nValue);
3694 : }
3695 93 : else if (eType == OFTInteger64List)
3696 : {
3697 1 : GIntBig nVal64 = nValue;
3698 1 : SetField(iField, 1, &nVal64);
3699 : }
3700 92 : else if (eType == OFTRealList)
3701 : {
3702 1 : double dfValue = nValue;
3703 1 : SetField(iField, 1, &dfValue);
3704 : }
3705 91 : else if (eType == OFTString)
3706 : {
3707 86 : char szTempBuffer[64] = {};
3708 :
3709 86 : snprintf(szTempBuffer, sizeof(szTempBuffer), "%d", nValue);
3710 :
3711 86 : if (IsFieldSetAndNotNullUnsafe(iField))
3712 83 : CPLFree(pauFields[iField].String);
3713 :
3714 86 : pauFields[iField].String = VSI_STRDUP_VERBOSE(szTempBuffer);
3715 86 : if (pauFields[iField].String == nullptr)
3716 : {
3717 0 : OGR_RawField_SetUnset(&pauFields[iField]);
3718 : }
3719 : }
3720 5 : else if (eType == OFTStringList)
3721 : {
3722 1 : char szTempBuffer[64] = {};
3723 :
3724 1 : snprintf(szTempBuffer, sizeof(szTempBuffer), "%d", nValue);
3725 1 : char *apszValues[2] = {szTempBuffer, nullptr};
3726 1 : SetField(iField, apszValues);
3727 : }
3728 : else
3729 : {
3730 : // Do nothing for other field types.
3731 : }
3732 : }
3733 :
3734 : /************************************************************************/
3735 : /* OGR_F_SetFieldInteger() */
3736 : /************************************************************************/
3737 :
3738 : /**
3739 : * \brief Set field to integer value.
3740 : *
3741 : * OFTInteger, OFTInteger64 and OFTReal fields will be set directly. OFTString
3742 : * fields will be assigned a string representation of the value, but not
3743 : * necessarily taking into account formatting constraints on this field. Other
3744 : * field types may be unaffected.
3745 : *
3746 : * This function is the same as the C++ method OGRFeature::SetField().
3747 : *
3748 : * @note This method has only an effect on the in-memory feature object. If
3749 : * this object comes from a layer and the modifications must be serialized back
3750 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
3751 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
3752 : *
3753 : * @param hFeat handle to the feature that owned the field.
3754 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3755 : * @param nValue the value to assign.
3756 : */
3757 :
3758 5033 : void OGR_F_SetFieldInteger(OGRFeatureH hFeat, int iField, int nValue)
3759 :
3760 : {
3761 5033 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldInteger");
3762 :
3763 5033 : OGRFeature::FromHandle(hFeat)->SetField(iField, nValue);
3764 : }
3765 :
3766 : /************************************************************************/
3767 : /* SetField() */
3768 : /************************************************************************/
3769 :
3770 : /**
3771 : * \fn OGRFeature::SetField( const char* pszFName, GIntBig nValue )
3772 : * \brief Set field to 64 bit integer value.
3773 : * OFTInteger, OFTInteger64 and OFTReal fields will be set directly. OFTString
3774 : * fields will be assigned a string representation of the value, but not
3775 : * necessarily taking into account formatting constraints on this field. Other
3776 : * field types may be unaffected.
3777 : *
3778 : * @note This method has only an effect on the in-memory feature object. If
3779 : * this object comes from a layer and the modifications must be serialized back
3780 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
3781 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
3782 : *
3783 : * @param pszFName the name of the field to set.
3784 : * @param nValue the value to assign.
3785 : */
3786 :
3787 : /**
3788 : * \brief Set field to 64 bit integer value.
3789 : *
3790 : * OFTInteger, OFTInteger64 and OFTReal fields will be set directly. OFTString
3791 : * fields will be assigned a string representation of the value, but not
3792 : * necessarily taking into account formatting constraints on this field. Other
3793 : * field types may be unaffected.
3794 : *
3795 : * This method is the same as the C function OGR_F_SetFieldInteger64().
3796 : *
3797 : * @note This method has only an effect on the in-memory feature object. If
3798 : * this object comes from a layer and the modifications must be serialized back
3799 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
3800 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
3801 : *
3802 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3803 : * @param nValue the value to assign.
3804 : */
3805 :
3806 96356 : void OGRFeature::SetField(int iField, GIntBig nValue)
3807 :
3808 : {
3809 96356 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3810 :
3811 96356 : if (poFDefn == nullptr)
3812 0 : return;
3813 :
3814 96356 : OGRFieldType eType = poFDefn->GetType();
3815 96356 : if (eType == OFTInteger)
3816 : {
3817 175746 : const int nVal32 = nValue < INT_MIN ? INT_MIN
3818 87873 : : nValue > INT_MAX ? INT_MAX
3819 : : static_cast<int>(nValue);
3820 :
3821 87873 : if (nVal32 != nValue)
3822 : {
3823 12 : CPLError(
3824 : CE_Warning, CPLE_AppDefined,
3825 : "Field %s.%s: integer overflow occurred when trying to set "
3826 : "%" PRId64 " as 32 bit integer.",
3827 6 : poDefn->GetName(), poFDefn->GetNameRef(),
3828 : static_cast<int64_t>(nValue));
3829 : }
3830 87873 : SetField(iField, nVal32);
3831 : }
3832 8483 : else if (eType == OFTInteger64)
3833 : {
3834 7713 : pauFields[iField].Integer64 = nValue;
3835 : }
3836 770 : else if (eType == OFTReal)
3837 : {
3838 650 : pauFields[iField].Real = static_cast<double>(nValue);
3839 : // Values in the range [INT64_MAX - 1023, INT64_MAX - 1]
3840 : // get converted to a double that once cast to int64_t is
3841 : // INT64_MAX + 1 ...
3842 1300 : if (pauFields[iField].Real >=
3843 1298 : static_cast<double>(std::numeric_limits<int64_t>::max()) ||
3844 648 : static_cast<GIntBig>(pauFields[iField].Real) != nValue)
3845 : {
3846 4 : CPLError(
3847 : CE_Warning, CPLE_AppDefined,
3848 : "Field %s.%s: Lossy conversion occurred when trying to set "
3849 : "a real field from 64 bit integer value %" PRId64 ".",
3850 2 : poDefn->GetName(), poFDefn->GetNameRef(),
3851 : static_cast<int64_t>(nValue));
3852 : }
3853 : }
3854 120 : else if (eType == OFTIntegerList)
3855 : {
3856 2 : int nVal32 = nValue < INT_MIN ? INT_MIN
3857 1 : : nValue > INT_MAX ? INT_MAX
3858 : : static_cast<int>(nValue);
3859 :
3860 1 : if (nVal32 != nValue)
3861 : {
3862 2 : CPLError(
3863 : CE_Warning, CPLE_AppDefined,
3864 : "Field %s.%s: Integer overflow occurred when trying to set "
3865 : "%" PRId64 " as 32 bit value.",
3866 1 : poDefn->GetName(), poFDefn->GetNameRef(),
3867 : static_cast<int64_t>(nValue));
3868 : }
3869 1 : SetField(iField, 1, &nVal32);
3870 : }
3871 119 : else if (eType == OFTInteger64List)
3872 : {
3873 11 : SetField(iField, 1, &nValue);
3874 : }
3875 108 : else if (eType == OFTRealList)
3876 : {
3877 1 : double dfValue = static_cast<double>(nValue);
3878 1 : SetField(iField, 1, &dfValue);
3879 : }
3880 107 : else if (eType == OFTString)
3881 : {
3882 102 : char szTempBuffer[64] = {};
3883 :
3884 102 : CPLsnprintf(szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB, nValue);
3885 :
3886 102 : if (IsFieldSetAndNotNullUnsafe(iField))
3887 2 : CPLFree(pauFields[iField].String);
3888 :
3889 102 : pauFields[iField].String = VSI_STRDUP_VERBOSE(szTempBuffer);
3890 102 : if (pauFields[iField].String == nullptr)
3891 : {
3892 0 : OGR_RawField_SetUnset(&pauFields[iField]);
3893 : }
3894 : }
3895 5 : else if (eType == OFTStringList)
3896 : {
3897 1 : char szTempBuffer[64] = {};
3898 :
3899 1 : CPLsnprintf(szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB, nValue);
3900 1 : char *apszValues[2] = {szTempBuffer, nullptr};
3901 1 : SetField(iField, apszValues);
3902 : }
3903 : else
3904 : {
3905 : // Do nothing for other field types.
3906 : }
3907 : }
3908 :
3909 : /************************************************************************/
3910 : /* OGR_F_SetFieldInteger64() */
3911 : /************************************************************************/
3912 :
3913 : /**
3914 : * \brief Set field to 64 bit integer value.
3915 : *
3916 : * OFTInteger, OFTInteger64 and OFTReal fields will be set directly. OFTString
3917 : * fields will be assigned a string representation of the value, but not
3918 : * necessarily taking into account formatting constraints on this field. Other
3919 : * field types may be unaffected.
3920 : *
3921 : * This function is the same as the C++ method OGRFeature::SetField().
3922 : *
3923 : * @note This method has only an effect on the in-memory feature object. If
3924 : * this object comes from a layer and the modifications must be serialized back
3925 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
3926 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
3927 : *
3928 : * @param hFeat handle to the feature that owned the field.
3929 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3930 : * @param nValue the value to assign.
3931 : */
3932 :
3933 85773 : void OGR_F_SetFieldInteger64(OGRFeatureH hFeat, int iField, GIntBig nValue)
3934 :
3935 : {
3936 85773 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldInteger64");
3937 :
3938 85773 : OGRFeature::FromHandle(hFeat)->SetField(iField, nValue);
3939 : }
3940 :
3941 : /************************************************************************/
3942 : /* SetField() */
3943 : /************************************************************************/
3944 :
3945 : /**
3946 : * \fn OGRFeature::SetField( const char* pszFName, double dfValue )
3947 : * \brief Set field to double value.
3948 : *
3949 : * OFTInteger, OFTInteger64 and OFTReal fields will be set directly. OFTString
3950 : * fields will be assigned a string representation of the value, but not
3951 : * necessarily taking into account formatting constraints on this field. Other
3952 : * field types may be unaffected.
3953 : *
3954 : * @note This method has only an effect on the in-memory feature object. If
3955 : * this object comes from a layer and the modifications must be serialized back
3956 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
3957 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
3958 : *
3959 : * @param pszFName the name of the field to set.
3960 : * @param dfValue the value to assign.
3961 : */
3962 :
3963 : /**
3964 : * \brief Set field to double value.
3965 : *
3966 : * OFTInteger, OFTInteger64 and OFTReal fields will be set directly. OFTString
3967 : * fields will be assigned a string representation of the value, but not
3968 : * necessarily taking into account formatting constraints on this field. Other
3969 : * field types may be unaffected.
3970 : *
3971 : * This method is the same as the C function OGR_F_SetFieldDouble().
3972 : *
3973 : * @note This method has only an effect on the in-memory feature object. If
3974 : * this object comes from a layer and the modifications must be serialized back
3975 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
3976 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
3977 : *
3978 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
3979 : * @param dfValue the value to assign.
3980 : */
3981 :
3982 71456 : void OGRFeature::SetField(int iField, double dfValue)
3983 :
3984 : {
3985 71456 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3986 :
3987 71456 : if (poFDefn == nullptr)
3988 0 : return;
3989 :
3990 71456 : const OGRFieldType eType = poFDefn->GetType();
3991 71456 : if (eType == OFTReal)
3992 : {
3993 : // if( poFDefn->GetSubType() == OFSTFloat32 &&
3994 : // dfValue != (double)(float)dfValue )
3995 : // {
3996 : // CPLError(CE_Warning, CPLE_AppDefined,
3997 : // "Passed value cannot be exactly representing as "
3998 : // "a single-precision floating point value.");
3999 : // dfValue = (double)(float)dfValue;
4000 : // }
4001 57264 : pauFields[iField].Real = dfValue;
4002 : }
4003 14192 : else if (eType == OFTInteger)
4004 : {
4005 13754 : constexpr int nMin = std::numeric_limits<int>::min();
4006 13754 : if (std::isnan(dfValue))
4007 : {
4008 2 : pauFields[iField].Integer = nMin;
4009 4 : CPLError(
4010 : CE_Warning, CPLE_AppDefined,
4011 : "Field %s.%s: Lossy conversion occurred when trying to set "
4012 : "32 bit integer field from real value %.17g.",
4013 2 : poDefn->GetName(), poFDefn->GetNameRef(), dfValue);
4014 : }
4015 : else
4016 : {
4017 13752 : constexpr int nMax = std::numeric_limits<int>::max();
4018 27504 : const int nVal = dfValue < nMin ? nMin
4019 13752 : : dfValue > nMax ? nMax
4020 13743 : : static_cast<int>(dfValue);
4021 27504 : pauFields[iField].Integer =
4022 13752 : OGRFeatureGetIntegerValue(poDefn, poFDefn, nVal);
4023 13752 : if (!(nVal == dfValue))
4024 : {
4025 28 : CPLError(
4026 : CE_Warning, CPLE_AppDefined,
4027 : "Field %s.%s: Lossy conversion occurred when trying to set "
4028 : "32 bit integer field from real value %.17g.",
4029 14 : poDefn->GetName(), poFDefn->GetNameRef(), dfValue);
4030 : }
4031 : }
4032 13754 : pauFields[iField].Set.nMarker2 = 0;
4033 13754 : pauFields[iField].Set.nMarker3 = 0;
4034 : }
4035 438 : else if (eType == OFTInteger64)
4036 : {
4037 400 : constexpr auto nMin = std::numeric_limits<GIntBig>::min();
4038 400 : if (std::isnan(dfValue))
4039 : {
4040 2 : pauFields[iField].Integer64 = nMin;
4041 4 : CPLError(
4042 : CE_Warning, CPLE_AppDefined,
4043 : "Field %s.%s: Lossy conversion occurred when trying to set "
4044 : "64 bit integer field from real value %.17g.",
4045 2 : poDefn->GetName(), poFDefn->GetNameRef(), dfValue);
4046 : }
4047 : else
4048 : {
4049 398 : constexpr auto nMax = std::numeric_limits<GIntBig>::max();
4050 796 : const auto nVal = dfValue < static_cast<double>(nMin) ? nMin
4051 398 : : dfValue > static_cast<double>(nMax)
4052 398 : ? nMax
4053 398 : : static_cast<GIntBig>(dfValue);
4054 398 : pauFields[iField].Integer64 = nVal;
4055 398 : if (!(static_cast<double>(nVal) == dfValue))
4056 : {
4057 8 : CPLError(
4058 : CE_Warning, CPLE_AppDefined,
4059 : "Field %s.%s: Lossy conversion occurred when trying to set "
4060 : "64 bit integer field from real value %.17g.",
4061 4 : poDefn->GetName(), poFDefn->GetNameRef(), dfValue);
4062 : }
4063 : }
4064 400 : pauFields[iField].Set.nMarker3 = 0;
4065 : }
4066 38 : else if (eType == OFTRealList)
4067 : {
4068 15 : SetField(iField, 1, &dfValue);
4069 : }
4070 23 : else if (eType == OFTIntegerList)
4071 : {
4072 1 : int nValue = static_cast<int>(dfValue);
4073 1 : SetField(iField, 1, &nValue);
4074 : }
4075 22 : else if (eType == OFTInteger64List)
4076 : {
4077 1 : GIntBig nValue = static_cast<GIntBig>(dfValue);
4078 1 : SetField(iField, 1, &nValue);
4079 : }
4080 21 : else if (eType == OFTString)
4081 : {
4082 16 : char szTempBuffer[128] = {};
4083 :
4084 16 : CPLsnprintf(szTempBuffer, sizeof(szTempBuffer), "%.16g", dfValue);
4085 :
4086 16 : if (IsFieldSetAndNotNullUnsafe(iField))
4087 7 : CPLFree(pauFields[iField].String);
4088 :
4089 16 : pauFields[iField].String = VSI_STRDUP_VERBOSE(szTempBuffer);
4090 16 : if (pauFields[iField].String == nullptr)
4091 : {
4092 0 : OGR_RawField_SetUnset(&pauFields[iField]);
4093 : }
4094 : }
4095 5 : else if (eType == OFTStringList)
4096 : {
4097 1 : char szTempBuffer[64] = {};
4098 :
4099 1 : CPLsnprintf(szTempBuffer, sizeof(szTempBuffer), "%.16g", dfValue);
4100 1 : char *apszValues[2] = {szTempBuffer, nullptr};
4101 1 : SetField(iField, apszValues);
4102 : }
4103 : else
4104 : {
4105 : // Do nothing for other field types.
4106 : }
4107 : }
4108 :
4109 : /************************************************************************/
4110 : /* OGR_F_SetFieldDouble() */
4111 : /************************************************************************/
4112 :
4113 : /**
4114 : * \brief Set field to double value.
4115 : *
4116 : * OFTInteger, OFTInteger64 and OFTReal fields will be set directly. OFTString
4117 : * fields will be assigned a string representation of the value, but not
4118 : * necessarily taking into account formatting constraints on this field. Other
4119 : * field types may be unaffected.
4120 : *
4121 : * This function is the same as the C++ method OGRFeature::SetField().
4122 : *
4123 : * @note This method has only an effect on the in-memory feature object. If
4124 : * this object comes from a layer and the modifications must be serialized back
4125 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4126 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4127 : *
4128 : * @param hFeat handle to the feature that owned the field.
4129 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
4130 : * @param dfValue the value to assign.
4131 : */
4132 :
4133 2131 : void OGR_F_SetFieldDouble(OGRFeatureH hFeat, int iField, double dfValue)
4134 :
4135 : {
4136 2131 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDouble");
4137 :
4138 2131 : OGRFeature::FromHandle(hFeat)->SetField(iField, dfValue);
4139 : }
4140 :
4141 : /************************************************************************/
4142 : /* SetField() */
4143 : /************************************************************************/
4144 :
4145 : /**
4146 : * \fn OGRFeature::SetField( const char* pszFName, const char * pszValue )
4147 : * \brief Set field to string value.
4148 : *
4149 : * OFTInteger fields will be set based on an atoi() conversion of the string.
4150 : * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the
4151 : * string. OFTReal fields will be set based on an CPLAtof() conversion of the
4152 : * string. Other field types may be unaffected.
4153 : *
4154 : * @note This method has only an effect on the in-memory feature object. If
4155 : * this object comes from a layer and the modifications must be serialized back
4156 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4157 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4158 : *
4159 : * @param pszFName the name of the field to set.
4160 : * @param pszValue the value to assign.
4161 : */
4162 :
4163 : /**
4164 : * \brief Set field to string value.
4165 : *
4166 : * OFTInteger fields will be set based on an atoi() conversion of the string.
4167 : * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the
4168 : * string. OFTReal fields will be set based on an CPLAtof() conversion of the
4169 : * string. Other field types may be unaffected.
4170 : *
4171 : * This method is the same as the C function OGR_F_SetFieldString().
4172 : *
4173 : * @note This method has only an effect on the in-memory feature object. If
4174 : * this object comes from a layer and the modifications must be serialized back
4175 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4176 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4177 : *
4178 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
4179 : * @param pszValue the value to assign.
4180 : */
4181 :
4182 2389250 : void OGRFeature::SetField(int iField, const char *pszValue)
4183 :
4184 : {
4185 : static int bWarn = -1;
4186 2389250 : if (bWarn < 0)
4187 401 : bWarn = CPLTestBool(
4188 : CPLGetConfigOption("OGR_SETFIELD_NUMERIC_WARNING", "YES"));
4189 :
4190 2389250 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
4191 2389250 : if (poFDefn == nullptr)
4192 1 : return;
4193 :
4194 2389250 : char *pszLast = nullptr;
4195 :
4196 2389250 : OGRFieldType eType = poFDefn->GetType();
4197 2389250 : if (eType == OFTString)
4198 : {
4199 2142820 : if (IsFieldSetAndNotNullUnsafe(iField))
4200 4462 : CPLFree(pauFields[iField].String);
4201 :
4202 2142820 : pauFields[iField].String = VSI_STRDUP_VERBOSE(pszValue ? pszValue : "");
4203 2142820 : if (pauFields[iField].String == nullptr)
4204 : {
4205 0 : OGR_RawField_SetUnset(&pauFields[iField]);
4206 : }
4207 : }
4208 246424 : else if (eType == OFTInteger)
4209 : {
4210 46127 : if (poFDefn->GetSubType() == OFSTBoolean)
4211 : {
4212 103 : constexpr char DIGIT_ZERO = '0';
4213 103 : if ((pszValue[0] == '1' && pszValue[1] == '\0') ||
4214 16 : EQUAL(pszValue, "true") || EQUAL(pszValue, "on") ||
4215 12 : EQUAL(pszValue, "yes"))
4216 : {
4217 92 : pauFields[iField].Integer = 1;
4218 92 : pauFields[iField].Set.nMarker2 = 0;
4219 92 : pauFields[iField].Set.nMarker3 = 0;
4220 : }
4221 11 : else if ((pszValue[0] == DIGIT_ZERO && pszValue[1] == '\0') ||
4222 7 : EQUAL(pszValue, "false") || EQUAL(pszValue, "off") ||
4223 4 : EQUAL(pszValue, "no"))
4224 : {
4225 8 : pauFields[iField].Integer = 0;
4226 8 : pauFields[iField].Set.nMarker2 = 0;
4227 8 : pauFields[iField].Set.nMarker3 = 0;
4228 : }
4229 : else
4230 : {
4231 3 : if (CPLGetValueType(pszValue) == CPL_VALUE_STRING)
4232 : {
4233 2 : CPLError(CE_Warning, CPLE_AppDefined,
4234 : "Invalid value '%s' for boolean field %s.%s. "
4235 : "Assuming it to be false.",
4236 1 : pszValue, poDefn->GetName(),
4237 : poFDefn->GetNameRef());
4238 1 : pauFields[iField].Integer = 0;
4239 1 : pauFields[iField].Set.nMarker2 = 0;
4240 1 : pauFields[iField].Set.nMarker3 = 0;
4241 : }
4242 : else
4243 : {
4244 4 : CPLError(CE_Warning, CPLE_AppDefined,
4245 : "Invalid value '%s' for boolean field %s.%s. "
4246 : "Assuming it to be true.",
4247 2 : pszValue, poDefn->GetName(),
4248 : poFDefn->GetNameRef());
4249 2 : pauFields[iField].Integer = 1;
4250 2 : pauFields[iField].Set.nMarker2 = 0;
4251 2 : pauFields[iField].Set.nMarker3 = 0;
4252 : }
4253 : }
4254 : }
4255 : else
4256 : {
4257 : // As allowed by C standard, some systems like MSVC do not reset errno.
4258 46024 : errno = 0;
4259 :
4260 46024 : long long nVal64 = std::strtoll(pszValue, &pszLast, 10);
4261 92033 : int nVal32 = nVal64 > INT_MAX ? INT_MAX
4262 46009 : : nVal64 < INT_MIN ? INT_MIN
4263 : : static_cast<int>(nVal64);
4264 92048 : pauFields[iField].Integer =
4265 46024 : OGRFeatureGetIntegerValue(poDefn, poFDefn, nVal32);
4266 46024 : if (bWarn && pauFields[iField].Integer == nVal32 &&
4267 46024 : (errno == ERANGE || nVal32 != nVal64 || !pszLast || *pszLast))
4268 21 : CPLError(CE_Warning, CPLE_AppDefined,
4269 : "Value '%s' of field %s.%s parsed incompletely to "
4270 : "integer %d.",
4271 21 : pszValue, poDefn->GetName(), poFDefn->GetNameRef(),
4272 21 : pauFields[iField].Integer);
4273 46024 : pauFields[iField].Set.nMarker2 = 0;
4274 46024 : pauFields[iField].Set.nMarker3 = 0;
4275 : }
4276 : }
4277 200297 : else if (eType == OFTInteger64)
4278 : {
4279 94104 : pauFields[iField].Integer64 = CPLAtoGIntBigEx(pszValue, bWarn, nullptr);
4280 94104 : pauFields[iField].Set.nMarker3 = 0;
4281 : }
4282 106193 : else if (eType == OFTReal)
4283 : {
4284 93965 : pauFields[iField].Real = CPLStrtod(pszValue, &pszLast);
4285 93965 : if (bWarn && (!pszLast || *pszLast))
4286 1 : CPLError(
4287 : CE_Warning, CPLE_AppDefined,
4288 : "Value '%s' of field %s.%s parsed incompletely to real %.16g.",
4289 1 : pszValue, poDefn->GetName(), poFDefn->GetNameRef(),
4290 1 : pauFields[iField].Real);
4291 : }
4292 12228 : else if (eType == OFTDate || eType == OFTTime || eType == OFTDateTime)
4293 : {
4294 : OGRField sWrkField;
4295 :
4296 11535 : if (OGRParseDate(pszValue, &sWrkField, 0))
4297 11535 : memcpy(pauFields + iField, &sWrkField, sizeof(sWrkField));
4298 : }
4299 693 : else if (eType == OFTIntegerList || eType == OFTInteger64List ||
4300 : eType == OFTRealList)
4301 : {
4302 490 : json_object *poJSonObj = nullptr;
4303 614 : if (pszValue[0] == '[' && pszValue[strlen(pszValue) - 1] == ']' &&
4304 124 : OGRJSonParse(pszValue, &poJSonObj, false))
4305 : {
4306 124 : const auto nLength = json_object_array_length(poJSonObj);
4307 124 : if (eType == OFTIntegerList && nLength > 0)
4308 : {
4309 124 : std::vector<int> anValues;
4310 193 : for (auto i = decltype(nLength){0}; i < nLength; i++)
4311 : {
4312 : json_object *poItem =
4313 131 : json_object_array_get_idx(poJSonObj, i);
4314 131 : anValues.push_back(json_object_get_int(poItem));
4315 : }
4316 124 : SetField(iField, static_cast<int>(nLength), &(anValues[0]));
4317 : }
4318 62 : else if (eType == OFTInteger64List && nLength > 0)
4319 : {
4320 46 : std::vector<GIntBig> anValues;
4321 70 : for (auto i = decltype(nLength){0}; i < nLength; i++)
4322 : {
4323 : json_object *poItem =
4324 47 : json_object_array_get_idx(poJSonObj, i);
4325 47 : anValues.push_back(json_object_get_int64(poItem));
4326 : }
4327 46 : SetField(iField, static_cast<int>(nLength), &(anValues[0]));
4328 : }
4329 39 : else if (eType == OFTRealList && nLength > 0)
4330 : {
4331 78 : std::vector<double> adfValues;
4332 120 : for (auto i = decltype(nLength){0}; i < nLength; i++)
4333 : {
4334 : json_object *poItem =
4335 81 : json_object_array_get_idx(poJSonObj, i);
4336 81 : adfValues.push_back(json_object_get_double(poItem));
4337 : }
4338 39 : SetField(iField, static_cast<int>(nLength), &(adfValues[0]));
4339 : }
4340 :
4341 124 : json_object_put(poJSonObj);
4342 : }
4343 : else
4344 : {
4345 366 : char **papszValueList = nullptr;
4346 :
4347 366 : if (pszValue[0] == '(' && strchr(pszValue, ':') != nullptr)
4348 : {
4349 363 : papszValueList = CSLTokenizeString2(pszValue, ",:()", 0);
4350 : }
4351 :
4352 729 : if (papszValueList == nullptr || *papszValueList == nullptr ||
4353 363 : atoi(papszValueList[0]) != CSLCount(papszValueList) - 1)
4354 : {
4355 : // Do nothing - the count does not match entries.
4356 : }
4357 363 : else if (eType == OFTIntegerList)
4358 : {
4359 131 : const int nCount = atoi(papszValueList[0]);
4360 262 : std::vector<int> anValues;
4361 131 : if (nCount == CSLCount(papszValueList) - 1)
4362 : {
4363 408 : for (int i = 0; i < nCount; i++)
4364 : {
4365 : // As allowed by C standard, some systems like
4366 : // MSVC do not reset errno.
4367 277 : errno = 0;
4368 277 : int nVal = atoi(papszValueList[i + 1]);
4369 277 : if (errno == ERANGE)
4370 : {
4371 0 : CPLError(
4372 : CE_Warning, CPLE_AppDefined,
4373 : "Field %s.%s: 32 bit integer overflow when "
4374 : "converting %s",
4375 0 : poDefn->GetName(), poFDefn->GetNameRef(),
4376 : pszValue);
4377 : }
4378 277 : anValues.push_back(nVal);
4379 : }
4380 131 : if (nCount > 0)
4381 131 : SetField(iField, nCount, &(anValues[0]));
4382 : }
4383 : }
4384 232 : else if (eType == OFTInteger64List)
4385 : {
4386 116 : const int nCount = atoi(papszValueList[0]);
4387 232 : std::vector<GIntBig> anValues;
4388 116 : if (nCount == CSLCount(papszValueList) - 1)
4389 : {
4390 232 : for (int i = 0; i < nCount; i++)
4391 : {
4392 232 : const GIntBig nVal = CPLAtoGIntBigEx(
4393 116 : papszValueList[i + 1], TRUE, nullptr);
4394 116 : anValues.push_back(nVal);
4395 : }
4396 116 : if (nCount > 0)
4397 116 : SetField(iField, nCount, &(anValues[0]));
4398 : }
4399 : }
4400 116 : else if (eType == OFTRealList)
4401 : {
4402 116 : int nCount = atoi(papszValueList[0]);
4403 232 : std::vector<double> adfValues;
4404 116 : if (nCount == CSLCount(papszValueList) - 1)
4405 : {
4406 232 : for (int i = 0; i < nCount; i++)
4407 116 : adfValues.push_back(CPLAtof(papszValueList[i + 1]));
4408 116 : if (nCount > 0)
4409 116 : SetField(iField, nCount, &(adfValues[0]));
4410 : }
4411 : }
4412 :
4413 366 : CSLDestroy(papszValueList);
4414 490 : }
4415 : }
4416 203 : else if (eType == OFTStringList)
4417 : {
4418 202 : if (pszValue && *pszValue)
4419 : {
4420 202 : json_object *poJSonObj = nullptr;
4421 202 : if (pszValue[0] == '(' && strchr(pszValue, ':') != nullptr &&
4422 116 : pszValue[strlen(pszValue) - 1] == ')')
4423 : {
4424 116 : char **papszValueList = CSLTokenizeString2(pszValue, ",:()", 0);
4425 116 : const int nCount =
4426 116 : papszValueList[0] == nullptr ? 0 : atoi(papszValueList[0]);
4427 232 : std::vector<char *> aosValues;
4428 116 : if (nCount == CSLCount(papszValueList) - 1)
4429 : {
4430 232 : for (int i = 0; i < nCount; i++)
4431 116 : aosValues.push_back(papszValueList[i + 1]);
4432 116 : aosValues.push_back(nullptr);
4433 116 : SetField(iField, &(aosValues[0]));
4434 : }
4435 232 : CSLDestroy(papszValueList);
4436 : }
4437 : // Is this a JSon array?
4438 226 : else if (pszValue[0] == '[' &&
4439 140 : pszValue[strlen(pszValue) - 1] == ']' &&
4440 54 : OGRJSonParse(pszValue, &poJSonObj, false))
4441 : {
4442 108 : CPLStringList aoList;
4443 54 : const auto nLength = json_object_array_length(poJSonObj);
4444 155 : for (auto i = decltype(nLength){0}; i < nLength; i++)
4445 : {
4446 : json_object *poItem =
4447 101 : json_object_array_get_idx(poJSonObj, i);
4448 101 : if (!poItem)
4449 2 : aoList.AddString("");
4450 : else
4451 99 : aoList.AddString(json_object_get_string(poItem));
4452 : }
4453 54 : SetField(iField, aoList.List());
4454 54 : json_object_put(poJSonObj);
4455 : }
4456 : else
4457 : {
4458 32 : const char *const papszValues[2] = {pszValue, nullptr};
4459 32 : SetField(iField, papszValues);
4460 : }
4461 : }
4462 : }
4463 : else
4464 : {
4465 : // Do nothing for other field types.
4466 : }
4467 : }
4468 :
4469 : /************************************************************************/
4470 : /* SetField() */
4471 : /************************************************************************/
4472 :
4473 : /**
4474 : * \brief Set field to string value.
4475 : *
4476 : * OFTInteger fields will be set based on an atoi() conversion of the string.
4477 : * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the
4478 : * string. OFTReal fields will be set based on an CPLAtof() conversion of the
4479 : * string. Other field types may be unaffected.
4480 : *
4481 : * This method is the same as the C function OGR_F_SetFieldString().
4482 : *
4483 : * @note This method has only an effect on the in-memory feature object. If
4484 : * this object comes from a layer and the modifications must be serialized back
4485 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4486 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4487 : *
4488 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
4489 : * @param svValue the value to assign.
4490 : * @since 3.13
4491 : */
4492 :
4493 0 : void OGRFeature::SetField(int iField, std::string_view svValue)
4494 :
4495 : {
4496 0 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
4497 0 : if (poFDefn == nullptr)
4498 0 : return;
4499 0 : if (poFDefn->GetType() == OFTString)
4500 : {
4501 0 : if (IsFieldSetAndNotNullUnsafe(iField))
4502 0 : CPLFree(pauFields[iField].String);
4503 :
4504 0 : pauFields[iField].String =
4505 0 : static_cast<char *>(VSI_MALLOC_VERBOSE(svValue.size() + 1));
4506 0 : if (pauFields[iField].String)
4507 : {
4508 0 : memcpy(pauFields[iField].String, svValue.data(), svValue.size());
4509 0 : pauFields[iField].String[svValue.size()] = 0;
4510 : }
4511 : else
4512 : {
4513 0 : OGR_RawField_SetUnset(&pauFields[iField]);
4514 : }
4515 : }
4516 : else
4517 : {
4518 0 : SetField(iField, std::string(svValue).c_str());
4519 : }
4520 : }
4521 :
4522 : /************************************************************************/
4523 : /* OGR_F_SetFieldString() */
4524 : /************************************************************************/
4525 :
4526 : /**
4527 : * \brief Set field to string value.
4528 : *
4529 : * OFTInteger fields will be set based on an atoi() conversion of the string.
4530 : * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the
4531 : * string. OFTReal fields will be set based on an CPLAtof() conversion of the
4532 : * string. Other field types may be unaffected.
4533 : *
4534 : * This function is the same as the C++ method OGRFeature::SetField().
4535 : *
4536 : * @note This method has only an effect on the in-memory feature object. If
4537 : * this object comes from a layer and the modifications must be serialized back
4538 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4539 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4540 : *
4541 : * @param hFeat handle to the feature that owned the field.
4542 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
4543 : * @param pszValue the value to assign.
4544 : */
4545 :
4546 12364 : void OGR_F_SetFieldString(OGRFeatureH hFeat, int iField, const char *pszValue)
4547 :
4548 : {
4549 12364 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldString");
4550 :
4551 12364 : OGRFeature::FromHandle(hFeat)->SetField(iField, pszValue);
4552 : }
4553 :
4554 : /************************************************************************/
4555 : /* SetField() */
4556 : /************************************************************************/
4557 :
4558 : /**
4559 : * \fn OGRFeature::SetField( const char* pszFName, int nCount, const int
4560 : * *panValues ) \brief Set field to list of integers value.
4561 : *
4562 : * This method currently on has an effect of OFTIntegerList, OFTInteger64List
4563 : * and OFTRealList fields.
4564 : *
4565 : * @note This method has only an effect on the in-memory feature object. If
4566 : * this object comes from a layer and the modifications must be serialized back
4567 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4568 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4569 : *
4570 : * @param pszFName the name of the field to set.
4571 : * @param nCount the number of values in the list being assigned.
4572 : * @param panValues the values to assign.
4573 : */
4574 :
4575 : /**
4576 : * \brief Set field to list of integers value.
4577 : *
4578 : * This method currently on has an effect of OFTIntegerList, OFTInteger64List
4579 : * and OFTRealList fields.
4580 : *
4581 : * This method is the same as the C function OGR_F_SetFieldIntegerList().
4582 : *
4583 : * @note This method has only an effect on the in-memory feature object. If
4584 : * this object comes from a layer and the modifications must be serialized back
4585 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4586 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4587 : *
4588 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4589 : * @param nCount the number of values in the list being assigned.
4590 : * @param panValues the values to assign.
4591 : */
4592 :
4593 32608 : void OGRFeature::SetField(int iField, int nCount, const int *panValues)
4594 :
4595 : {
4596 32608 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
4597 :
4598 32608 : if (poFDefn == nullptr)
4599 0 : return;
4600 :
4601 32608 : OGRFieldType eType = poFDefn->GetType();
4602 32608 : if (eType == OFTIntegerList)
4603 : {
4604 : OGRField uField;
4605 32598 : int *panValuesMod = nullptr;
4606 :
4607 57930 : if (poFDefn->GetSubType() == OFSTBoolean ||
4608 25332 : poFDefn->GetSubType() == OFSTInt16)
4609 : {
4610 21654 : for (int i = 0; i < nCount; i++)
4611 : {
4612 : int nVal =
4613 13966 : OGRFeatureGetIntegerValue(poDefn, poFDefn, panValues[i]);
4614 13966 : if (panValues[i] != nVal)
4615 : {
4616 2 : if (panValuesMod == nullptr)
4617 : {
4618 : panValuesMod = static_cast<int *>(
4619 2 : VSI_MALLOC_VERBOSE(nCount * sizeof(int)));
4620 2 : if (panValuesMod == nullptr)
4621 0 : return;
4622 2 : if (nCount > 0)
4623 2 : memcpy(panValuesMod, panValues,
4624 2 : nCount * sizeof(int));
4625 : }
4626 2 : panValuesMod[i] = nVal;
4627 : }
4628 : }
4629 : }
4630 :
4631 32598 : uField.IntegerList.nCount = nCount;
4632 32598 : uField.Set.nMarker2 = 0;
4633 32598 : uField.Set.nMarker3 = 0;
4634 32598 : uField.IntegerList.paList =
4635 32598 : panValuesMod ? panValuesMod : const_cast<int *>(panValues);
4636 :
4637 32598 : SetField(iField, &uField);
4638 32598 : CPLFree(panValuesMod);
4639 : }
4640 10 : else if (eType == OFTInteger64List)
4641 : {
4642 2 : std::vector<GIntBig> anValues;
4643 1 : anValues.reserve(nCount);
4644 4 : for (int i = 0; i < nCount; i++)
4645 3 : anValues.push_back(panValues[i]);
4646 1 : if (nCount > 0)
4647 1 : SetField(iField, nCount, &anValues[0]);
4648 : }
4649 9 : else if (eType == OFTRealList)
4650 : {
4651 2 : std::vector<double> adfValues;
4652 1 : adfValues.reserve(nCount);
4653 4 : for (int i = 0; i < nCount; i++)
4654 3 : adfValues.push_back(static_cast<double>(panValues[i]));
4655 1 : if (nCount > 0)
4656 1 : SetField(iField, nCount, &adfValues[0]);
4657 : }
4658 8 : else if ((eType == OFTInteger || eType == OFTInteger64 ||
4659 3 : eType == OFTReal) &&
4660 : nCount == 1)
4661 : {
4662 3 : SetField(iField, panValues[0]);
4663 : }
4664 5 : else if (eType == OFTStringList)
4665 : {
4666 : char **papszValues = static_cast<char **>(
4667 1 : VSI_MALLOC_VERBOSE((nCount + 1) * sizeof(char *)));
4668 1 : if (papszValues == nullptr)
4669 0 : return;
4670 4 : for (int i = 0; i < nCount; i++)
4671 3 : papszValues[i] = VSI_STRDUP_VERBOSE(CPLSPrintf("%d", panValues[i]));
4672 1 : papszValues[nCount] = nullptr;
4673 1 : SetField(iField, papszValues);
4674 1 : CSLDestroy(papszValues);
4675 : }
4676 : }
4677 :
4678 : /************************************************************************/
4679 : /* OGR_F_SetFieldIntegerList() */
4680 : /************************************************************************/
4681 :
4682 : /**
4683 : * \brief Set field to list of integers value.
4684 : *
4685 : * This function currently on has an effect of OFTIntegerList, OFTInteger64List
4686 : * and OFTRealList fields.
4687 : *
4688 : * This function is the same as the C++ method OGRFeature::SetField().
4689 : *
4690 : * @note This method has only an effect on the in-memory feature object. If
4691 : * this object comes from a layer and the modifications must be serialized back
4692 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4693 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4694 : *
4695 : * @param hFeat handle to the feature that owned the field.
4696 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4697 : * @param nCount the number of values in the list being assigned.
4698 : * @param panValues the values to assign.
4699 : */
4700 :
4701 9 : void OGR_F_SetFieldIntegerList(OGRFeatureH hFeat, int iField, int nCount,
4702 : const int *panValues)
4703 :
4704 : {
4705 9 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldIntegerList");
4706 :
4707 9 : OGRFeature::FromHandle(hFeat)->SetField(iField, nCount, panValues);
4708 : }
4709 :
4710 : /************************************************************************/
4711 : /* SetField() */
4712 : /************************************************************************/
4713 :
4714 : /**
4715 : * \fn OGRFeature::SetField( const char* pszFName, int nCount, const GIntBig
4716 : * *panValues )
4717 : * \brief Set field to list of 64 bit integers value.
4718 : *
4719 : * This method currently on has an effect of OFTIntegerList, OFTInteger64List
4720 : * and OFTRealList fields.
4721 : *
4722 : * @note This method has only an effect on the in-memory feature object. If
4723 : * this object comes from a layer and the modifications must be serialized back
4724 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4725 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4726 : *
4727 : * @param pszFName the name of the field to set.
4728 : * @param nCount the number of values in the list being assigned.
4729 : * @param panValues the values to assign.
4730 : */
4731 :
4732 : /**
4733 : * \brief Set field to list of 64 bit integers value.
4734 : *
4735 : * This method currently on has an effect of OFTIntegerList, OFTInteger64List
4736 : * and OFTRealList fields.
4737 : *
4738 : * This method is the same as the C function OGR_F_SetFieldInteger64List().
4739 : *
4740 : * @note This method has only an effect on the in-memory feature object. If
4741 : * this object comes from a layer and the modifications must be serialized back
4742 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4743 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4744 : *
4745 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4746 : * @param nCount the number of values in the list being assigned.
4747 : * @param panValues the values to assign.
4748 : */
4749 :
4750 12864 : void OGRFeature::SetField(int iField, int nCount, const GIntBig *panValues)
4751 :
4752 : {
4753 12864 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
4754 :
4755 12864 : if (poFDefn == nullptr)
4756 0 : return;
4757 :
4758 12864 : OGRFieldType eType = poFDefn->GetType();
4759 12864 : if (eType == OFTIntegerList)
4760 : {
4761 150 : std::vector<int> anValues;
4762 :
4763 406 : for (int i = 0; i < nCount; i++)
4764 : {
4765 331 : const GIntBig nValue = panValues[i];
4766 662 : const int nVal32 = nValue < INT_MIN ? INT_MIN
4767 331 : : nValue > INT_MAX ? INT_MAX
4768 : : static_cast<int>(nValue);
4769 :
4770 331 : if (nVal32 != nValue)
4771 : {
4772 2 : CPLError(
4773 : CE_Warning, CPLE_AppDefined,
4774 : "Field %s.%s: Integer overflow occurred when trying to "
4775 : "set %" PRId64 " as 32 bit value.",
4776 1 : poDefn->GetName(), poFDefn->GetNameRef(),
4777 : static_cast<int64_t>(nValue));
4778 : }
4779 331 : anValues.push_back(nVal32);
4780 : }
4781 75 : if (nCount > 0)
4782 75 : SetField(iField, nCount, &anValues[0]);
4783 : }
4784 12789 : else if (eType == OFTInteger64List)
4785 : {
4786 : OGRField uField;
4787 12779 : uField.Integer64List.nCount = nCount;
4788 12779 : uField.Set.nMarker2 = 0;
4789 12779 : uField.Set.nMarker3 = 0;
4790 12779 : uField.Integer64List.paList = const_cast<GIntBig *>(panValues);
4791 :
4792 12779 : SetField(iField, &uField);
4793 : }
4794 10 : else if (eType == OFTRealList)
4795 : {
4796 4 : std::vector<double> adfValues;
4797 2 : adfValues.reserve(nCount);
4798 103 : for (int i = 0; i < nCount; i++)
4799 101 : adfValues.push_back(static_cast<double>(panValues[i]));
4800 2 : if (nCount > 0)
4801 2 : SetField(iField, nCount, &adfValues[0]);
4802 : }
4803 8 : else if ((eType == OFTInteger || eType == OFTInteger64 ||
4804 3 : eType == OFTReal) &&
4805 : nCount == 1)
4806 : {
4807 3 : SetField(iField, panValues[0]);
4808 : }
4809 5 : else if (eType == OFTStringList)
4810 : {
4811 : char **papszValues = static_cast<char **>(
4812 1 : VSI_MALLOC_VERBOSE((nCount + 1) * sizeof(char *)));
4813 1 : if (papszValues == nullptr)
4814 0 : return;
4815 2 : for (int i = 0; i < nCount; i++)
4816 2 : papszValues[i] =
4817 1 : VSI_STRDUP_VERBOSE(CPLSPrintf(CPL_FRMT_GIB, panValues[i]));
4818 1 : papszValues[nCount] = nullptr;
4819 1 : SetField(iField, papszValues);
4820 1 : CSLDestroy(papszValues);
4821 : }
4822 : }
4823 :
4824 : /************************************************************************/
4825 : /* OGR_F_SetFieldInteger64List() */
4826 : /************************************************************************/
4827 :
4828 : /**
4829 : * \brief Set field to list of 64 bit integers value.
4830 : *
4831 : * This function currently on has an effect of OFTIntegerList, OFTInteger64List
4832 : * and OFTRealList fields.
4833 : *
4834 : * This function is the same as the C++ method OGRFeature::SetField().
4835 : *
4836 : * @note This method has only an effect on the in-memory feature object. If
4837 : * this object comes from a layer and the modifications must be serialized back
4838 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4839 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4840 : *
4841 : * @param hFeat handle to the feature that owned the field.
4842 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4843 : * @param nCount the number of values in the list being assigned.
4844 : * @param panValues the values to assign.
4845 : */
4846 :
4847 124 : void OGR_F_SetFieldInteger64List(OGRFeatureH hFeat, int iField, int nCount,
4848 : const GIntBig *panValues)
4849 :
4850 : {
4851 124 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldInteger64List");
4852 :
4853 124 : OGRFeature::FromHandle(hFeat)->SetField(iField, nCount, panValues);
4854 : }
4855 :
4856 : /************************************************************************/
4857 : /* SetField() */
4858 : /************************************************************************/
4859 :
4860 : /**
4861 : * \fn OGRFeature::SetField( const char* pszFName, int nCount, const double *
4862 : * padfValues ) \brief Set field to list of doubles value.
4863 : *
4864 : * This method currently on has an effect of OFTIntegerList, OFTInteger64List,
4865 : * OFTRealList fields.
4866 : *
4867 : * @note This method has only an effect on the in-memory feature object. If
4868 : * this object comes from a layer and the modifications must be serialized back
4869 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4870 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4871 : *
4872 : * @param pszFName the name of the field to set.
4873 : * @param nCount the number of values in the list being assigned.
4874 : * @param padfValues the values to assign.
4875 : */
4876 :
4877 : /**
4878 : * \brief Set field to list of doubles value.
4879 : *
4880 : * This method currently on has an effect of OFTIntegerList, OFTInteger64List,
4881 : * OFTRealList fields.
4882 : *
4883 : * This method is the same as the C function OGR_F_SetFieldDoubleList().
4884 : *
4885 : * @note This method has only an effect on the in-memory feature object. If
4886 : * this object comes from a layer and the modifications must be serialized back
4887 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4888 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4889 : *
4890 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4891 : * @param nCount the number of values in the list being assigned.
4892 : * @param padfValues the values to assign.
4893 : */
4894 :
4895 21127 : void OGRFeature::SetField(int iField, int nCount, const double *padfValues)
4896 :
4897 : {
4898 21127 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
4899 :
4900 21127 : if (poFDefn == nullptr)
4901 0 : return;
4902 :
4903 21127 : OGRFieldType eType = poFDefn->GetType();
4904 21127 : if (eType == OFTRealList)
4905 : {
4906 : OGRField uField;
4907 :
4908 20870 : uField.RealList.nCount = nCount;
4909 20870 : uField.Set.nMarker2 = 0;
4910 20870 : uField.Set.nMarker3 = 0;
4911 20870 : uField.RealList.paList = const_cast<double *>(padfValues);
4912 :
4913 20870 : SetField(iField, &uField);
4914 : }
4915 257 : else if (eType == OFTIntegerList)
4916 : {
4917 366 : std::vector<int> anValues;
4918 183 : anValues.reserve(nCount);
4919 507 : for (int i = 0; i < nCount; i++)
4920 324 : anValues.push_back(static_cast<int>(padfValues[i]));
4921 :
4922 183 : if (nCount > 0)
4923 183 : SetField(iField, nCount, &anValues[0]);
4924 : }
4925 74 : else if (eType == OFTInteger64List)
4926 : {
4927 4 : std::vector<GIntBig> anValues;
4928 2 : anValues.reserve(nCount);
4929 5 : for (int i = 0; i < nCount; i++)
4930 3 : anValues.push_back(static_cast<GIntBig>(padfValues[i]));
4931 2 : if (nCount > 0)
4932 2 : SetField(iField, nCount, &anValues[0]);
4933 : }
4934 72 : else if ((eType == OFTInteger || eType == OFTInteger64 ||
4935 67 : eType == OFTReal) &&
4936 : nCount == 1)
4937 : {
4938 67 : SetField(iField, padfValues[0]);
4939 : }
4940 5 : else if (eType == OFTStringList)
4941 : {
4942 : char **papszValues = static_cast<char **>(
4943 1 : VSI_MALLOC_VERBOSE((nCount + 1) * sizeof(char *)));
4944 1 : if (papszValues == nullptr)
4945 0 : return;
4946 3 : for (int i = 0; i < nCount; i++)
4947 4 : papszValues[i] =
4948 2 : VSI_STRDUP_VERBOSE(CPLSPrintf("%.16g", padfValues[i]));
4949 1 : papszValues[nCount] = nullptr;
4950 1 : SetField(iField, papszValues);
4951 1 : CSLDestroy(papszValues);
4952 : }
4953 : }
4954 :
4955 : /************************************************************************/
4956 : /* OGR_F_SetFieldDoubleList() */
4957 : /************************************************************************/
4958 :
4959 : /**
4960 : * \brief Set field to list of doubles value.
4961 : *
4962 : * This function currently on has an effect of OFTIntegerList, OFTInteger64List,
4963 : * OFTRealList fields.
4964 : *
4965 : * This function is the same as the C++ method OGRFeature::SetField().
4966 : *
4967 : * @note This method has only an effect on the in-memory feature object. If
4968 : * this object comes from a layer and the modifications must be serialized back
4969 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4970 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4971 : *
4972 : * @param hFeat handle to the feature that owned the field.
4973 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4974 : * @param nCount the number of values in the list being assigned.
4975 : * @param padfValues the values to assign.
4976 : */
4977 :
4978 91 : void OGR_F_SetFieldDoubleList(OGRFeatureH hFeat, int iField, int nCount,
4979 : const double *padfValues)
4980 :
4981 : {
4982 91 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDoubleList");
4983 :
4984 91 : OGRFeature::FromHandle(hFeat)->SetField(iField, nCount, padfValues);
4985 : }
4986 :
4987 : /************************************************************************/
4988 : /* SetField() */
4989 : /************************************************************************/
4990 :
4991 : /**
4992 : * \fn OGRFeature::SetField( const char* pszFName, const char * const *
4993 : * papszValues ) \brief Set field to list of strings value.
4994 : *
4995 : * This method currently on has an effect of OFTStringList fields.
4996 : *
4997 : * @note This method has only an effect on the in-memory feature object. If
4998 : * this object comes from a layer and the modifications must be serialized back
4999 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5000 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5001 : *
5002 : * @param pszFName the name of the field to set.
5003 : * @param papszValues the values to assign. List of NUL-terminated string,
5004 : * ending with a NULL pointer.
5005 : */
5006 :
5007 : /**
5008 : * \brief Set field to list of strings value.
5009 : *
5010 : * This method currently on has an effect of OFTStringList fields.
5011 : *
5012 : * This method is the same as the C function OGR_F_SetFieldStringList().
5013 : *
5014 : * @note This method has only an effect on the in-memory feature object. If
5015 : * this object comes from a layer and the modifications must be serialized back
5016 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5017 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5018 : *
5019 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5020 : * @param papszValues the values to assign. List of NUL-terminated string,
5021 : * ending with a NULL pointer.
5022 : */
5023 :
5024 37806 : void OGRFeature::SetField(int iField, const char *const *papszValues)
5025 :
5026 : {
5027 37806 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
5028 :
5029 37806 : if (poFDefn == nullptr)
5030 0 : return;
5031 :
5032 37806 : OGRFieldType eType = poFDefn->GetType();
5033 37806 : if (eType == OFTStringList)
5034 : {
5035 24570 : if (!IsFieldSetAndNotNullUnsafe(iField) ||
5036 5629 : papszValues != pauFields[iField].StringList.paList)
5037 : {
5038 : OGRField uField;
5039 :
5040 18939 : uField.StringList.nCount = CSLCount(papszValues);
5041 18939 : uField.Set.nMarker2 = 0;
5042 18939 : uField.Set.nMarker3 = 0;
5043 18939 : uField.StringList.paList = const_cast<char **>(papszValues);
5044 :
5045 18939 : SetField(iField, &uField);
5046 : }
5047 : }
5048 18865 : else if (eType == OFTIntegerList)
5049 : {
5050 9845 : const int nValues = CSLCount(papszValues);
5051 : int *panValues =
5052 9845 : static_cast<int *>(VSI_MALLOC_VERBOSE(nValues * sizeof(int)));
5053 9845 : if (panValues == nullptr)
5054 0 : return;
5055 28447 : for (int i = 0; i < nValues; i++)
5056 : {
5057 : // As allowed by C standard, some systems like MSVC do not
5058 : // reset errno.
5059 18602 : errno = 0;
5060 :
5061 18602 : int nVal = atoi(papszValues[i]);
5062 18602 : if (errno == ERANGE)
5063 : {
5064 0 : CPLError(
5065 : CE_Warning, CPLE_AppDefined,
5066 : "Field %s.%s: 32 bit integer overflow when converting %s",
5067 0 : poDefn->GetName(), poFDefn->GetNameRef(), papszValues[i]);
5068 0 : if (papszValues[i][0] == '-')
5069 0 : nVal = INT_MIN;
5070 : else
5071 0 : nVal = INT_MAX;
5072 : }
5073 18602 : panValues[i] = nVal;
5074 : }
5075 9845 : SetField(iField, nValues, panValues);
5076 9845 : CPLFree(panValues);
5077 : }
5078 9020 : else if (eType == OFTInteger64List)
5079 : {
5080 3377 : const int nValues = CSLCount(papszValues);
5081 : GIntBig *panValues = static_cast<GIntBig *>(
5082 3377 : VSI_MALLOC_VERBOSE(nValues * sizeof(GIntBig)));
5083 3377 : if (panValues == nullptr)
5084 0 : return;
5085 10073 : for (int i = 0; i < nValues; i++)
5086 : {
5087 6696 : panValues[i] = CPLAtoGIntBigEx(papszValues[i], TRUE, nullptr);
5088 : }
5089 3377 : SetField(iField, nValues, panValues);
5090 3377 : CPLFree(panValues);
5091 : }
5092 5643 : else if (eType == OFTRealList)
5093 : {
5094 5643 : const int nValues = CSLCount(papszValues);
5095 : double *padfValues =
5096 5643 : static_cast<double *>(VSI_MALLOC_VERBOSE(nValues * sizeof(double)));
5097 5643 : if (padfValues == nullptr)
5098 0 : return;
5099 15738 : for (int i = 0; i < nValues; i++)
5100 : {
5101 10095 : padfValues[i] = CPLAtof(papszValues[i]);
5102 : }
5103 5643 : SetField(iField, nValues, padfValues);
5104 5643 : CPLFree(padfValues);
5105 : }
5106 : }
5107 :
5108 : /************************************************************************/
5109 : /* OGR_F_SetFieldStringList() */
5110 : /************************************************************************/
5111 :
5112 : /**
5113 : * \brief Set field to list of strings value.
5114 : *
5115 : * This function currently on has an effect of OFTStringList fields.
5116 : *
5117 : * This function is the same as the C++ method OGRFeature::SetField().
5118 : *
5119 : * @note This method has only an effect on the in-memory feature object. If
5120 : * this object comes from a layer and the modifications must be serialized back
5121 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5122 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5123 : *
5124 : * @param hFeat handle to the feature that owned the field.
5125 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5126 : * @param papszValues the values to assign. List of NUL-terminated string,
5127 : * ending with a NULL pointer.
5128 : */
5129 :
5130 44 : void OGR_F_SetFieldStringList(OGRFeatureH hFeat, int iField,
5131 : CSLConstList papszValues)
5132 :
5133 : {
5134 44 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldStringList");
5135 :
5136 44 : OGRFeature::FromHandle(hFeat)->SetField(iField, papszValues);
5137 : }
5138 :
5139 : /************************************************************************/
5140 : /* SetField() */
5141 : /************************************************************************/
5142 :
5143 : /**
5144 : * \brief Set field to binary data.
5145 : *
5146 : * This method currently on has an effect of OFTBinary fields.
5147 : *
5148 : * This method is the same as the C function OGR_F_SetFieldBinary().
5149 : *
5150 : * @note This method has only an effect on the in-memory feature object. If
5151 : * this object comes from a layer and the modifications must be serialized back
5152 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5153 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5154 : *
5155 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5156 : * @param nBytes bytes of data being set.
5157 : * @param pabyData the raw data being applied.
5158 : */
5159 :
5160 18017 : void OGRFeature::SetField(int iField, int nBytes, const void *pabyData)
5161 :
5162 : {
5163 18017 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
5164 :
5165 18017 : if (poFDefn == nullptr)
5166 0 : return;
5167 :
5168 18017 : OGRFieldType eType = poFDefn->GetType();
5169 18017 : if (eType == OFTBinary)
5170 : {
5171 : OGRField uField;
5172 :
5173 18014 : uField.Binary.nCount = nBytes;
5174 18014 : uField.Set.nMarker2 = 0;
5175 18014 : uField.Set.nMarker3 = 0;
5176 18014 : uField.Binary.paData =
5177 : const_cast<GByte *>(static_cast<const GByte *>(pabyData));
5178 :
5179 18014 : SetField(iField, &uField);
5180 : }
5181 3 : else if (eType == OFTString || eType == OFTStringList)
5182 : {
5183 3 : char *pszStr = static_cast<char *>(VSI_MALLOC_VERBOSE(nBytes + 1));
5184 3 : if (pszStr == nullptr)
5185 0 : return;
5186 3 : if (nBytes > 0)
5187 3 : memcpy(pszStr, pabyData, nBytes);
5188 3 : pszStr[nBytes] = 0;
5189 3 : SetField(iField, pszStr);
5190 3 : CPLFree(pszStr);
5191 : }
5192 : }
5193 :
5194 : /************************************************************************/
5195 : /* OGR_F_SetFieldBinary() */
5196 : /************************************************************************/
5197 :
5198 : /**
5199 : * \brief Set field to binary data.
5200 : *
5201 : * This function currently on has an effect of OFTBinary fields.
5202 : *
5203 : * This function is the same as the C++ method OGRFeature::SetField().
5204 : *
5205 : * @note This method has only an effect on the in-memory feature object. If
5206 : * this object comes from a layer and the modifications must be serialized back
5207 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5208 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5209 : *
5210 : * @param hFeat handle to the feature that owned the field.
5211 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5212 : * @param nBytes the number of bytes in pabyData array.
5213 : * @param pabyData the data to apply.
5214 : */
5215 :
5216 524 : void OGR_F_SetFieldBinary(OGRFeatureH hFeat, int iField, int nBytes,
5217 : const void *pabyData)
5218 :
5219 : {
5220 524 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldBinary");
5221 :
5222 524 : OGRFeature::FromHandle(hFeat)->SetField(iField, nBytes, pabyData);
5223 : }
5224 :
5225 : /************************************************************************/
5226 : /* SetField() */
5227 : /************************************************************************/
5228 :
5229 : /**
5230 : * \fn OGRFeature::SetField( const char* pszFName, int nYear, int nMonth,
5231 : * int nDay, int nHour, int nMinute, float fSecond,
5232 : * int nTZFlag )
5233 : * \brief Set field to date.
5234 : *
5235 : * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
5236 : * fields.
5237 : *
5238 : * @note This method has only an effect on the in-memory feature object. If
5239 : * this object comes from a layer and the modifications must be serialized back
5240 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5241 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5242 : *
5243 : * @param pszFName the name of the field to set.
5244 : * @param nYear (including century)
5245 : * @param nMonth (1-12)
5246 : * @param nDay (1-31)
5247 : * @param nHour (0-23)
5248 : * @param nMinute (0-59)
5249 : * @param fSecond (0-59, with millisecond accuracy)
5250 : * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
5251 : */
5252 :
5253 : /**
5254 : * \brief Set field to date.
5255 : *
5256 : * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
5257 : * fields.
5258 : *
5259 : * This method is the same as the C function OGR_F_SetFieldDateTime().
5260 : *
5261 : * @note This method has only an effect on the in-memory feature object. If
5262 : * this object comes from a layer and the modifications must be serialized back
5263 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5264 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5265 : *
5266 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5267 : * @param nYear (including century)
5268 : * @param nMonth (1-12)
5269 : * @param nDay (1-31)
5270 : * @param nHour (0-23)
5271 : * @param nMinute (0-59)
5272 : * @param fSecond (0-59, with millisecond accuracy)
5273 : * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
5274 : */
5275 :
5276 10705 : void OGRFeature::SetField(int iField, int nYear, int nMonth, int nDay,
5277 : int nHour, int nMinute, float fSecond, int nTZFlag)
5278 :
5279 : {
5280 10705 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
5281 :
5282 10705 : if (poFDefn == nullptr)
5283 0 : return;
5284 :
5285 10705 : OGRFieldType eType = poFDefn->GetType();
5286 10705 : if (eType == OFTDate || eType == OFTTime || eType == OFTDateTime)
5287 : {
5288 10697 : if (static_cast<GInt16>(nYear) != nYear)
5289 : {
5290 0 : CPLError(CE_Failure, CPLE_NotSupported,
5291 : "Years < -32768 or > 32767 are not supported");
5292 0 : return;
5293 : }
5294 :
5295 10697 : pauFields[iField].Date.Year = static_cast<GInt16>(nYear);
5296 10697 : pauFields[iField].Date.Month = static_cast<GByte>(nMonth);
5297 10697 : pauFields[iField].Date.Day = static_cast<GByte>(nDay);
5298 10697 : pauFields[iField].Date.Hour = static_cast<GByte>(nHour);
5299 10697 : pauFields[iField].Date.Minute = static_cast<GByte>(nMinute);
5300 10697 : pauFields[iField].Date.Second = fSecond;
5301 10697 : pauFields[iField].Date.TZFlag = static_cast<GByte>(nTZFlag);
5302 : }
5303 8 : else if (eType == OFTString || eType == OFTStringList)
5304 : {
5305 : // "YYYY/MM/DD HH:MM:SS.sss+ZZ"
5306 8 : constexpr size_t MAX_SIZE = 26 + 1;
5307 8 : char szTempBuffer[MAX_SIZE] = {};
5308 8 : OGRFeatureFormatDateTimeBuffer(szTempBuffer, MAX_SIZE, nYear, nMonth,
5309 : nDay, nHour, nMinute, fSecond, nTZFlag);
5310 8 : SetField(iField, szTempBuffer);
5311 : }
5312 : }
5313 :
5314 : /************************************************************************/
5315 : /* OGR_F_SetFieldDateTime() */
5316 : /************************************************************************/
5317 :
5318 : /**
5319 : * \brief Set field to datetime.
5320 : *
5321 : * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
5322 : * fields.
5323 : *
5324 : * @note This method has only an effect on the in-memory feature object. If
5325 : * this object comes from a layer and the modifications must be serialized back
5326 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5327 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5328 : *
5329 : * @param hFeat handle to the feature that owned the field.
5330 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5331 : * @param nYear (including century)
5332 : * @param nMonth (1-12)
5333 : * @param nDay (1-31)
5334 : * @param nHour (0-23)
5335 : * @param nMinute (0-59)
5336 : * @param nSecond (0-59)
5337 : * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
5338 : *
5339 : * @see Use OGR_F_SetFieldDateTimeEx() for second with millisecond accuracy.
5340 : */
5341 :
5342 0 : void OGR_F_SetFieldDateTime(OGRFeatureH hFeat, int iField, int nYear,
5343 : int nMonth, int nDay, int nHour, int nMinute,
5344 : int nSecond, int nTZFlag)
5345 :
5346 : {
5347 0 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDateTime");
5348 :
5349 0 : OGRFeature::FromHandle(hFeat)->SetField(
5350 : iField, nYear, nMonth, nDay, nHour, nMinute,
5351 : static_cast<float>(nSecond), nTZFlag);
5352 : }
5353 :
5354 : /************************************************************************/
5355 : /* OGR_F_SetFieldDateTimeEx() */
5356 : /************************************************************************/
5357 :
5358 : /**
5359 : * \brief Set field to datetime.
5360 : *
5361 : * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
5362 : * fields.
5363 : *
5364 : * @note This method has only an effect on the in-memory feature object. If
5365 : * this object comes from a layer and the modifications must be serialized back
5366 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5367 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5368 : *
5369 : * @param hFeat handle to the feature that owned the field.
5370 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5371 : * @param nYear (including century)
5372 : * @param nMonth (1-12)
5373 : * @param nDay (1-31)
5374 : * @param nHour (0-23)
5375 : * @param nMinute (0-59)
5376 : * @param fSecond (0-59, with millisecond accuracy)
5377 : * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
5378 : *
5379 : */
5380 :
5381 45 : void OGR_F_SetFieldDateTimeEx(OGRFeatureH hFeat, int iField, int nYear,
5382 : int nMonth, int nDay, int nHour, int nMinute,
5383 : float fSecond, int nTZFlag)
5384 :
5385 : {
5386 45 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDateTimeEx");
5387 :
5388 45 : OGRFeature::FromHandle(hFeat)->SetField(iField, nYear, nMonth, nDay, nHour,
5389 : nMinute, fSecond, nTZFlag);
5390 : }
5391 :
5392 : /************************************************************************/
5393 : /* SetField() */
5394 : /************************************************************************/
5395 :
5396 : /**
5397 : * \fn OGRFeature::SetField( const char* pszFName, const OGRField * puValue )
5398 : * \brief Set field.
5399 : *
5400 : * The passed value OGRField must be of exactly the same type as the
5401 : * target field, or an application crash may occur. The passed value
5402 : * is copied, and will not be affected. It remains the responsibility of
5403 : * the caller.
5404 : *
5405 : * @note This method has only an effect on the in-memory feature object. If
5406 : * this object comes from a layer and the modifications must be serialized back
5407 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5408 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5409 : *
5410 : * @param pszFName the name of the field to set.
5411 : * @param puValue the value to assign.
5412 : */
5413 :
5414 : /**
5415 : * \brief Set field.
5416 : *
5417 : * The passed value OGRField must be of exactly the same type as the
5418 : * target field, or an application crash may occur. The passed value
5419 : * is copied, and will not be affected. It remains the responsibility of
5420 : * the caller.
5421 : *
5422 : * This method is the same as the C function OGR_F_SetFieldRaw().
5423 : *
5424 : * @note This method has only an effect on the in-memory feature object. If
5425 : * this object comes from a layer and the modifications must be serialized back
5426 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5427 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5428 : *
5429 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
5430 : * @param puValue the value to assign.
5431 : */
5432 :
5433 390928 : void OGRFeature::SetField(int iField, const OGRField *puValue)
5434 :
5435 : {
5436 390928 : SetFieldInternal(iField, puValue);
5437 390928 : }
5438 :
5439 4624030 : bool OGRFeature::SetFieldInternal(int iField, const OGRField *puValue)
5440 :
5441 : {
5442 4624030 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
5443 4624030 : if (iField < 0 || poFDefn == nullptr)
5444 0 : return false;
5445 :
5446 4624030 : if (poFDefn->GetType() == OFTInteger)
5447 : {
5448 1315600 : pauFields[iField] = *puValue;
5449 : }
5450 3308430 : else if (poFDefn->GetType() == OFTInteger64)
5451 : {
5452 26004 : pauFields[iField] = *puValue;
5453 : }
5454 3282430 : else if (poFDefn->GetType() == OFTReal)
5455 : {
5456 77877 : pauFields[iField] = *puValue;
5457 : }
5458 3204550 : else if (poFDefn->GetType() == OFTString)
5459 : {
5460 2911090 : if (IsFieldSetAndNotNullUnsafe(iField))
5461 28 : CPLFree(pauFields[iField].String);
5462 :
5463 2911090 : if (puValue->String == nullptr)
5464 0 : pauFields[iField].String = nullptr;
5465 2911090 : else if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
5466 1217950 : pauFields[iField] = *puValue;
5467 : else
5468 : {
5469 1693140 : pauFields[iField].String = VSI_STRDUP_VERBOSE(puValue->String);
5470 1693140 : if (pauFields[iField].String == nullptr)
5471 : {
5472 0 : OGR_RawField_SetUnset(&pauFields[iField]);
5473 0 : return false;
5474 : }
5475 : }
5476 : }
5477 542428 : else if (poFDefn->GetType() == OFTDate || poFDefn->GetType() == OFTTime ||
5478 248963 : poFDefn->GetType() == OFTDateTime)
5479 : {
5480 105660 : memcpy(pauFields + iField, puValue, sizeof(OGRField));
5481 : }
5482 187805 : else if (poFDefn->GetType() == OFTIntegerList)
5483 : {
5484 43845 : const int nCount = puValue->IntegerList.nCount;
5485 :
5486 43845 : if (IsFieldSetAndNotNullUnsafe(iField))
5487 3343 : CPLFree(pauFields[iField].IntegerList.paList);
5488 :
5489 43845 : if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
5490 : {
5491 350 : pauFields[iField] = *puValue;
5492 : }
5493 : else
5494 : {
5495 86990 : pauFields[iField].IntegerList.paList =
5496 43495 : static_cast<int *>(VSI_MALLOC_VERBOSE(sizeof(int) * nCount));
5497 43495 : if (pauFields[iField].IntegerList.paList == nullptr)
5498 : {
5499 0 : OGR_RawField_SetUnset(&pauFields[iField]);
5500 0 : return false;
5501 : }
5502 43495 : if (nCount > 0)
5503 : {
5504 40487 : memcpy(pauFields[iField].IntegerList.paList,
5505 40487 : puValue->IntegerList.paList, sizeof(int) * nCount);
5506 : }
5507 43495 : pauFields[iField].IntegerList.nCount = nCount;
5508 : }
5509 : }
5510 143960 : else if (poFDefn->GetType() == OFTInteger64List)
5511 : {
5512 23326 : const int nCount = puValue->Integer64List.nCount;
5513 :
5514 23326 : if (IsFieldSetAndNotNullUnsafe(iField))
5515 1168 : CPLFree(pauFields[iField].Integer64List.paList);
5516 :
5517 23326 : if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
5518 : {
5519 111 : pauFields[iField] = *puValue;
5520 : }
5521 : else
5522 : {
5523 46430 : pauFields[iField].Integer64List.paList = static_cast<GIntBig *>(
5524 23215 : VSI_MALLOC_VERBOSE(sizeof(GIntBig) * nCount));
5525 23215 : if (pauFields[iField].Integer64List.paList == nullptr)
5526 : {
5527 0 : OGR_RawField_SetUnset(&pauFields[iField]);
5528 0 : return false;
5529 : }
5530 23215 : if (nCount > 0)
5531 : {
5532 22252 : memcpy(pauFields[iField].Integer64List.paList,
5533 22252 : puValue->Integer64List.paList, sizeof(GIntBig) * nCount);
5534 : }
5535 23215 : pauFields[iField].Integer64List.nCount = nCount;
5536 : }
5537 : }
5538 120634 : else if (poFDefn->GetType() == OFTRealList)
5539 : {
5540 32047 : const int nCount = puValue->RealList.nCount;
5541 :
5542 32047 : if (IsFieldSetAndNotNullUnsafe(iField))
5543 2343 : CPLFree(pauFields[iField].RealList.paList);
5544 :
5545 32047 : if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
5546 : {
5547 10412 : pauFields[iField] = *puValue;
5548 : }
5549 : else
5550 : {
5551 43270 : pauFields[iField].RealList.paList = static_cast<double *>(
5552 21635 : VSI_MALLOC_VERBOSE(sizeof(double) * nCount));
5553 21635 : if (pauFields[iField].RealList.paList == nullptr)
5554 : {
5555 0 : OGR_RawField_SetUnset(&pauFields[iField]);
5556 0 : return false;
5557 : }
5558 21635 : if (nCount > 0)
5559 : {
5560 20012 : memcpy(pauFields[iField].RealList.paList,
5561 20012 : puValue->RealList.paList, sizeof(double) * nCount);
5562 : }
5563 21635 : pauFields[iField].RealList.nCount = nCount;
5564 : }
5565 : }
5566 88587 : else if (poFDefn->GetType() == OFTStringList)
5567 : {
5568 29679 : if (IsFieldSetAndNotNullUnsafe(iField))
5569 5627 : CSLDestroy(pauFields[iField].StringList.paList);
5570 :
5571 29679 : if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
5572 : {
5573 272 : pauFields[iField] = *puValue;
5574 : }
5575 : else
5576 : {
5577 29407 : char **papszNewList = nullptr;
5578 29407 : for (char **papszIter = puValue->StringList.paList;
5579 84325 : papszIter != nullptr && *papszIter != nullptr; ++papszIter)
5580 : {
5581 : char **papszNewList2 =
5582 54918 : CSLAddStringMayFail(papszNewList, *papszIter);
5583 54918 : if (papszNewList2 == nullptr)
5584 : {
5585 0 : CSLDestroy(papszNewList);
5586 0 : OGR_RawField_SetUnset(&pauFields[iField]);
5587 0 : return false;
5588 : }
5589 54918 : papszNewList = papszNewList2;
5590 : }
5591 29407 : pauFields[iField].StringList.paList = papszNewList;
5592 29407 : pauFields[iField].StringList.nCount = puValue->StringList.nCount;
5593 29407 : CPLAssert(CSLCount(puValue->StringList.paList) ==
5594 : puValue->StringList.nCount);
5595 : }
5596 : }
5597 58908 : else if (poFDefn->GetType() == OFTBinary)
5598 : {
5599 58908 : if (IsFieldSetAndNotNullUnsafe(iField))
5600 103 : CPLFree(pauFields[iField].Binary.paData);
5601 :
5602 58908 : if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
5603 : {
5604 105 : pauFields[iField] = *puValue;
5605 : }
5606 : else
5607 : {
5608 117606 : pauFields[iField].Binary.paData = static_cast<GByte *>(
5609 58803 : VSI_MALLOC_VERBOSE(puValue->Binary.nCount));
5610 58803 : if (pauFields[iField].Binary.paData == nullptr)
5611 : {
5612 0 : OGR_RawField_SetUnset(&pauFields[iField]);
5613 0 : return false;
5614 : }
5615 58803 : if (puValue->Binary.nCount > 0)
5616 : {
5617 58760 : memcpy(pauFields[iField].Binary.paData, puValue->Binary.paData,
5618 58760 : puValue->Binary.nCount);
5619 : }
5620 58803 : pauFields[iField].Binary.nCount = puValue->Binary.nCount;
5621 : }
5622 : }
5623 : else
5624 : {
5625 : // Do nothing for other field types.
5626 : }
5627 4624030 : return true;
5628 : }
5629 :
5630 : /************************************************************************/
5631 : /* OGR_F_SetFieldRaw() */
5632 : /************************************************************************/
5633 :
5634 : /**
5635 : * \brief Set field.
5636 : *
5637 : * The passed value OGRField must be of exactly the same type as the
5638 : * target field, or an application crash may occur. The passed value
5639 : * is copied, and will not be affected. It remains the responsibility of
5640 : * the caller.
5641 : *
5642 : * This function is the same as the C++ method OGRFeature::SetField().
5643 : *
5644 : * @note This method has only an effect on the in-memory feature object. If
5645 : * this object comes from a layer and the modifications must be serialized back
5646 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5647 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5648 : *
5649 : * @param hFeat handle to the feature that owned the field.
5650 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
5651 : * @param psValue handle on the value to assign.
5652 : */
5653 :
5654 0 : void OGR_F_SetFieldRaw(OGRFeatureH hFeat, int iField, const OGRField *psValue)
5655 :
5656 : {
5657 0 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldRaw");
5658 :
5659 0 : OGRFeature::FromHandle(hFeat)->SetField(iField, psValue);
5660 : }
5661 :
5662 : /************************************************************************/
5663 : /* DumpReadable() */
5664 : /************************************************************************/
5665 :
5666 : /**
5667 : * \brief Dump this feature in a human readable form.
5668 : *
5669 : * This dumps the attributes, and geometry; however, it doesn't definition
5670 : * information (other than field types and names), nor does it report the
5671 : * geometry spatial reference system.
5672 : *
5673 : * A few options can be defined to change the default dump :
5674 : * <ul>
5675 : * <li>DISPLAY_FIELDS=NO : to hide the dump of the attributes</li>
5676 : * <li>DISPLAY_STYLE=NO : to hide the dump of the style string</li>
5677 : * <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
5678 : * <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
5679 : * </ul>
5680 : *
5681 : * This method is the same as the C function OGR_F_DumpReadable().
5682 : *
5683 : * @param fpOut the stream to write to, such as stdout. If NULL stdout will
5684 : * be used.
5685 : * @param papszOptions NULL terminated list of options (may be NULL)
5686 : */
5687 :
5688 121 : void OGRFeature::DumpReadable(FILE *fpOut, CSLConstList papszOptions) const
5689 :
5690 : {
5691 121 : if (fpOut == nullptr)
5692 121 : fpOut = stdout;
5693 :
5694 242 : const auto osStr = DumpReadableAsString(papszOptions);
5695 121 : fprintf(fpOut, "%s", osStr.c_str());
5696 121 : }
5697 :
5698 : /************************************************************************/
5699 : /* DumpReadableAsString() */
5700 : /************************************************************************/
5701 :
5702 : /**
5703 : * \brief Dump this feature in a human readable form.
5704 : *
5705 : * This dumps the attributes, and geometry; however, it doesn't definition
5706 : * information (other than field types and names), nor does it report the
5707 : * geometry spatial reference system.
5708 : *
5709 : * A few options can be defined to change the default dump :
5710 : * <ul>
5711 : * <li>DISPLAY_FIELDS=NO : to hide the dump of the attributes</li>
5712 : * <li>DISPLAY_STYLE=NO : to hide the dump of the style string</li>
5713 : * <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
5714 : * <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
5715 : * </ul>
5716 : *
5717 : * @param papszOptions NULL terminated list of options (may be NULL)
5718 : * @return a string with the feature representation.
5719 : * @since GDAL 3.7
5720 : */
5721 :
5722 827 : std::string OGRFeature::DumpReadableAsString(CSLConstList papszOptions) const
5723 : {
5724 827 : std::string osRet;
5725 :
5726 1654 : osRet += CPLOPrintf("OGRFeature(%s):" CPL_FRMT_GIB "\n", poDefn->GetName(),
5727 827 : GetFID());
5728 :
5729 : const char *pszDisplayFields =
5730 827 : CSLFetchNameValue(papszOptions, "DISPLAY_FIELDS");
5731 827 : if (pszDisplayFields == nullptr || CPLTestBool(pszDisplayFields))
5732 : {
5733 816 : const int nFieldCount = GetFieldCount();
5734 8168 : for (int iField = 0; iField < nFieldCount; iField++)
5735 : {
5736 7352 : if (!IsFieldSet(iField))
5737 2560 : continue;
5738 4792 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefnUnsafe(iField);
5739 :
5740 : const char *pszType =
5741 4792 : (poFDefn->GetSubType() != OFSTNone)
5742 4792 : ? CPLSPrintf(
5743 : "%s(%s)",
5744 : poFDefn->GetFieldTypeName(poFDefn->GetType()),
5745 : poFDefn->GetFieldSubTypeName(poFDefn->GetSubType()))
5746 4354 : : poFDefn->GetFieldTypeName(poFDefn->GetType());
5747 :
5748 4792 : osRet += CPLOPrintf(" %s (%s) = ", poFDefn->GetNameRef(), pszType);
5749 :
5750 4792 : if (IsFieldNull(iField))
5751 45 : osRet += "(null)\n";
5752 : else
5753 4747 : osRet += CPLOPrintf("%s\n", GetFieldAsString(iField));
5754 : }
5755 : }
5756 :
5757 827 : if (GetStyleString() != nullptr)
5758 : {
5759 : const char *pszDisplayStyle =
5760 4 : CSLFetchNameValue(papszOptions, "DISPLAY_STYLE");
5761 4 : if (pszDisplayStyle == nullptr || CPLTestBool(pszDisplayStyle))
5762 : {
5763 4 : osRet += CPLOPrintf(" Style = %s\n", GetStyleString());
5764 : }
5765 : }
5766 :
5767 827 : const int nGeomFieldCount = GetGeomFieldCount();
5768 827 : if (nGeomFieldCount > 0)
5769 : {
5770 : const char *pszDisplayGeometry =
5771 311 : CSLFetchNameValue(papszOptions, "DISPLAY_GEOMETRY");
5772 311 : if (!(pszDisplayGeometry != nullptr && EQUAL(pszDisplayGeometry, "NO")))
5773 : {
5774 606 : for (int iField = 0; iField < nGeomFieldCount; iField++)
5775 : {
5776 : const OGRGeomFieldDefn *poFDefn =
5777 306 : poDefn->GetGeomFieldDefn(iField);
5778 :
5779 306 : if (papoGeometries[iField] != nullptr)
5780 : {
5781 303 : CPLStringList aosGeomOptions(papszOptions);
5782 :
5783 303 : const auto &oCoordPrec = poFDefn->GetCoordinatePrecision();
5784 :
5785 303 : if (oCoordPrec.dfXYResolution !=
5786 : OGRGeomCoordinatePrecision::UNKNOWN)
5787 : {
5788 : aosGeomOptions.SetNameValue(
5789 : "XY_COORD_PRECISION",
5790 : CPLSPrintf("%d",
5791 : OGRGeomCoordinatePrecision::
5792 : ResolutionToPrecision(
5793 1 : oCoordPrec.dfXYResolution)));
5794 : }
5795 303 : if (oCoordPrec.dfZResolution !=
5796 : OGRGeomCoordinatePrecision::UNKNOWN)
5797 : {
5798 : aosGeomOptions.SetNameValue(
5799 : "Z_COORD_PRECISION",
5800 : CPLSPrintf("%d",
5801 : OGRGeomCoordinatePrecision::
5802 : ResolutionToPrecision(
5803 1 : oCoordPrec.dfZResolution)));
5804 : }
5805 :
5806 303 : osRet += " ";
5807 355 : if (strlen(poFDefn->GetNameRef()) > 0 &&
5808 52 : GetGeomFieldCount() > 1)
5809 12 : osRet += CPLOPrintf("%s = ", poFDefn->GetNameRef());
5810 606 : osRet += papoGeometries[iField]->dumpReadable(
5811 606 : nullptr, aosGeomOptions.List());
5812 : }
5813 : }
5814 : }
5815 : }
5816 :
5817 827 : osRet += "\n";
5818 827 : return osRet;
5819 : }
5820 :
5821 : /************************************************************************/
5822 : /* OGR_F_DumpReadable() */
5823 : /************************************************************************/
5824 :
5825 : /**
5826 : * \brief Dump this feature in a human readable form.
5827 : *
5828 : * This dumps the attributes, and geometry; however, it doesn't definition
5829 : * information (other than field types and names), nor does it report the
5830 : * geometry spatial reference system.
5831 : *
5832 : * This function is the same as the C++ method OGRFeature::DumpReadable().
5833 : *
5834 : * @param hFeat handle to the feature to dump.
5835 : * @param fpOut the stream to write to, such as strout.
5836 : */
5837 :
5838 31 : void OGR_F_DumpReadable(OGRFeatureH hFeat, FILE *fpOut)
5839 :
5840 : {
5841 31 : VALIDATE_POINTER0(hFeat, "OGR_F_DumpReadable");
5842 :
5843 31 : OGRFeature::FromHandle(hFeat)->DumpReadable(fpOut);
5844 : }
5845 :
5846 : /************************************************************************/
5847 : /* OGR_F_DumpReadableAsString() */
5848 : /************************************************************************/
5849 :
5850 : /**
5851 : * \brief Dump this feature in a human readable form.
5852 : *
5853 : * This dumps the attributes, and geometry; however, it doesn't include
5854 : * definition information (other than field types and names), nor does
5855 : * it report the geometry spatial reference system.
5856 : *
5857 : * A few options can be defined to change the default dump :
5858 : * <ul>
5859 : * <li>DISPLAY_FIELDS=NO : to hide the dump of the attributes</li>
5860 : * <li>DISPLAY_STYLE=NO : to hide the dump of the style string</li>
5861 : * <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
5862 : * <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
5863 : * </ul>
5864 : *
5865 : * @param hFeat handle to the feature to dump.
5866 : * @param papszOptions NULL terminated list of options (may be NULL)
5867 : * @return a string with the feature representation (to be freed with CPLFree())
5868 : * @since GDAL 3.8
5869 : */
5870 :
5871 96 : char *OGR_F_DumpReadableAsString(OGRFeatureH hFeat, CSLConstList papszOptions)
5872 : {
5873 96 : VALIDATE_POINTER1(hFeat, "OGR_F_DumpReadableAsString", nullptr);
5874 :
5875 96 : return CPLStrdup(OGRFeature::FromHandle(hFeat)
5876 192 : ->DumpReadableAsString(papszOptions)
5877 96 : .c_str());
5878 : }
5879 :
5880 : /************************************************************************/
5881 : /* GetFID() */
5882 : /************************************************************************/
5883 :
5884 : /**
5885 : * \fn GIntBig OGRFeature::GetFID() const;
5886 : *
5887 : * \brief Get feature identifier.
5888 : *
5889 : * This method is the same as the C function OGR_F_GetFID().
5890 : *
5891 : * @return feature id or OGRNullFID if none has been assigned.
5892 : */
5893 :
5894 : /************************************************************************/
5895 : /* OGR_F_GetFID() */
5896 : /************************************************************************/
5897 :
5898 : /**
5899 : * \brief Get feature identifier.
5900 : *
5901 : * This function is the same as the C++ method OGRFeature::GetFID().
5902 : *
5903 : * @param hFeat handle to the feature from which to get the feature
5904 : * identifier.
5905 : * @return feature id or OGRNullFID if none has been assigned.
5906 : */
5907 :
5908 5475 : GIntBig OGR_F_GetFID(OGRFeatureH hFeat)
5909 :
5910 : {
5911 5475 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFID", 0);
5912 :
5913 5475 : return OGRFeature::FromHandle(hFeat)->GetFID();
5914 : }
5915 :
5916 : /************************************************************************/
5917 : /* SetFID() */
5918 : /************************************************************************/
5919 :
5920 : /**
5921 : * \brief Set the feature identifier.
5922 : *
5923 : * For specific types of features this operation may fail on illegal
5924 : * features ids. Generally it always succeeds. Feature ids should be
5925 : * greater than or equal to zero, with the exception of OGRNullFID (-1)
5926 : * indicating that the feature id is unknown.
5927 : *
5928 : * This method is the same as the C function OGR_F_SetFID().
5929 : *
5930 : * @param nFIDIn the new feature identifier value to assign.
5931 : *
5932 : * @return On success OGRERR_NONE, or on failure some other value.
5933 : */
5934 :
5935 3049040 : OGRErr OGRFeature::SetFID(GIntBig nFIDIn)
5936 :
5937 : {
5938 3049040 : nFID = nFIDIn;
5939 :
5940 3049040 : return OGRERR_NONE;
5941 : }
5942 :
5943 : /************************************************************************/
5944 : /* OGR_F_SetFID() */
5945 : /************************************************************************/
5946 :
5947 : /**
5948 : * \brief Set the feature identifier.
5949 : *
5950 : * For specific types of features this operation may fail on illegal
5951 : * features ids. Generally it always succeeds. Feature ids should be
5952 : * greater than or equal to zero, with the exception of OGRNullFID (-1)
5953 : * indicating that the feature id is unknown.
5954 : *
5955 : * This function is the same as the C++ method OGRFeature::SetFID().
5956 : *
5957 : * @param hFeat handle to the feature to set the feature id to.
5958 : * @param nFID the new feature identifier value to assign.
5959 : *
5960 : * @return On success OGRERR_NONE, or on failure some other value.
5961 : */
5962 :
5963 170912 : OGRErr OGR_F_SetFID(OGRFeatureH hFeat, GIntBig nFID)
5964 :
5965 : {
5966 170912 : VALIDATE_POINTER1(hFeat, "OGR_F_SetFID", OGRERR_FAILURE);
5967 :
5968 170912 : return OGRFeature::FromHandle(hFeat)->SetFID(nFID);
5969 : }
5970 :
5971 : /************************************************************************/
5972 : /* Equal() */
5973 : /************************************************************************/
5974 :
5975 : /**
5976 : * \brief Test if two features are the same.
5977 : *
5978 : * Two features are considered equal if the share them (pointer equality)
5979 : * same OGRFeatureDefn, have the same field values, and the same geometry
5980 : * (as tested by OGRGeometry::Equal()) as well as the same feature id.
5981 : *
5982 : * This method is the same as the C function OGR_F_Equal().
5983 : *
5984 : * @param poFeature the other feature to test this one against.
5985 : *
5986 : * @return TRUE if they are equal, otherwise FALSE.
5987 : */
5988 :
5989 56445 : OGRBoolean OGRFeature::Equal(const OGRFeature *poFeature) const
5990 :
5991 : {
5992 56445 : if (poFeature == this)
5993 1 : return TRUE;
5994 :
5995 56444 : if (GetFID() != poFeature->GetFID())
5996 53315 : return FALSE;
5997 :
5998 3129 : if (GetDefnRef() != poFeature->GetDefnRef())
5999 11 : return FALSE;
6000 :
6001 3118 : const int nFields = GetDefnRef()->GetFieldCountUnsafe();
6002 27324 : for (int i = 0; i < nFields; i++)
6003 : {
6004 24321 : if (IsFieldSet(i) != poFeature->IsFieldSet(i))
6005 2 : return FALSE;
6006 24319 : if (IsFieldNull(i) != poFeature->IsFieldNull(i))
6007 0 : return FALSE;
6008 24319 : if (!IsFieldSetAndNotNullUnsafe(i))
6009 3552 : continue;
6010 :
6011 20767 : switch (GetDefnRef()->GetFieldDefnUnsafe(i)->GetType())
6012 : {
6013 5676 : case OFTInteger:
6014 5676 : if (GetFieldAsInteger(i) != poFeature->GetFieldAsInteger(i))
6015 18 : return FALSE;
6016 5658 : break;
6017 :
6018 669 : case OFTInteger64:
6019 669 : if (GetFieldAsInteger64(i) != poFeature->GetFieldAsInteger64(i))
6020 4 : return FALSE;
6021 665 : break;
6022 :
6023 4250 : case OFTReal:
6024 : {
6025 4250 : const double dfVal1 = GetFieldAsDouble(i);
6026 4250 : const double dfVal2 = poFeature->GetFieldAsDouble(i);
6027 4250 : if (std::isnan(dfVal1))
6028 : {
6029 7 : if (!std::isnan(dfVal2))
6030 1 : return FALSE;
6031 : }
6032 4243 : else if (std::isnan(dfVal2))
6033 : {
6034 1 : return FALSE;
6035 : }
6036 4242 : else if (dfVal1 != dfVal2)
6037 : {
6038 16 : return FALSE;
6039 : }
6040 4232 : break;
6041 : }
6042 :
6043 5575 : case OFTString:
6044 5575 : if (strcmp(GetFieldAsString(i),
6045 5575 : poFeature->GetFieldAsString(i)) != 0)
6046 15 : return FALSE;
6047 5560 : break;
6048 :
6049 447 : case OFTIntegerList:
6050 : {
6051 447 : int nCount1 = 0;
6052 447 : int nCount2 = 0;
6053 447 : const int *pnList1 = GetFieldAsIntegerList(i, &nCount1);
6054 : const int *pnList2 =
6055 447 : poFeature->GetFieldAsIntegerList(i, &nCount2);
6056 447 : if (nCount1 != nCount2)
6057 4 : return FALSE;
6058 1247 : for (int j = 0; j < nCount1; j++)
6059 : {
6060 804 : if (pnList1[j] != pnList2[j])
6061 2 : return FALSE;
6062 : }
6063 443 : break;
6064 : }
6065 :
6066 168 : case OFTInteger64List:
6067 : {
6068 168 : int nCount1 = 0;
6069 168 : int nCount2 = 0;
6070 168 : const GIntBig *pnList1 = GetFieldAsInteger64List(i, &nCount1);
6071 : const GIntBig *pnList2 =
6072 168 : poFeature->GetFieldAsInteger64List(i, &nCount2);
6073 168 : if (nCount1 != nCount2)
6074 0 : return FALSE;
6075 497 : for (int j = 0; j < nCount1; j++)
6076 : {
6077 329 : if (pnList1[j] != pnList2[j])
6078 0 : return FALSE;
6079 : }
6080 168 : break;
6081 : }
6082 :
6083 326 : case OFTRealList:
6084 : {
6085 326 : int nCount1 = 0;
6086 326 : int nCount2 = 0;
6087 326 : const double *padfList1 = GetFieldAsDoubleList(i, &nCount1);
6088 : const double *padfList2 =
6089 326 : poFeature->GetFieldAsDoubleList(i, &nCount2);
6090 326 : if (nCount1 != nCount2)
6091 6 : return FALSE;
6092 928 : for (int j = 0; j < nCount1; j++)
6093 : {
6094 608 : const double dfVal1 = padfList1[j];
6095 608 : const double dfVal2 = padfList2[j];
6096 608 : if (std::isnan(dfVal1))
6097 : {
6098 126 : if (!std::isnan(dfVal2))
6099 1 : return FALSE;
6100 : }
6101 482 : else if (std::isnan(dfVal2))
6102 : {
6103 1 : return FALSE;
6104 : }
6105 481 : else if (dfVal1 != dfVal2)
6106 : {
6107 2 : return FALSE;
6108 : }
6109 : }
6110 320 : break;
6111 : }
6112 :
6113 170 : case OFTStringList:
6114 : {
6115 170 : int nCount1 = 0;
6116 170 : int nCount2 = 0;
6117 170 : char **papszList1 = GetFieldAsStringList(i);
6118 170 : char **papszList2 = poFeature->GetFieldAsStringList(i);
6119 170 : nCount1 = CSLCount(papszList1);
6120 170 : nCount2 = CSLCount(papszList2);
6121 170 : if (nCount1 != nCount2)
6122 2 : return FALSE;
6123 430 : for (int j = 0; j < nCount1; j++)
6124 : {
6125 264 : if (strcmp(papszList1[j], papszList2[j]) != 0)
6126 2 : return FALSE;
6127 : }
6128 166 : break;
6129 : }
6130 :
6131 1472 : case OFTTime:
6132 : case OFTDate:
6133 : case OFTDateTime:
6134 : {
6135 1472 : int nYear1 = 0;
6136 1472 : int nMonth1 = 0;
6137 1472 : int nDay1 = 0;
6138 1472 : int nHour1 = 0;
6139 1472 : int nMinute1 = 0;
6140 1472 : int nTZFlag1 = 0;
6141 1472 : int nYear2 = 0;
6142 1472 : int nMonth2 = 0;
6143 1472 : int nDay2 = 0;
6144 1472 : int nHour2 = 0;
6145 1472 : int nMinute2 = 0;
6146 1472 : int nTZFlag2 = 0;
6147 1472 : float fSecond1 = 0.0f;
6148 1472 : float fSecond2 = 0.0f;
6149 1472 : GetFieldAsDateTime(i, &nYear1, &nMonth1, &nDay1, &nHour1,
6150 : &nMinute1, &fSecond1, &nTZFlag1);
6151 1472 : poFeature->GetFieldAsDateTime(i, &nYear2, &nMonth2, &nDay2,
6152 : &nHour2, &nMinute2, &fSecond2,
6153 : &nTZFlag2);
6154 :
6155 1472 : if (!(nYear1 == nYear2 && nMonth1 == nMonth2 &&
6156 1460 : nDay1 == nDay2 && nHour1 == nHour2 &&
6157 1448 : nMinute1 == nMinute2 && fSecond1 == fSecond2 &&
6158 1436 : nTZFlag1 == nTZFlag2))
6159 42 : return FALSE;
6160 1430 : break;
6161 : }
6162 :
6163 2014 : case OFTBinary:
6164 : {
6165 2014 : int nCount1 = 0;
6166 2014 : int nCount2 = 0;
6167 2014 : GByte *pabyData1 = GetFieldAsBinary(i, &nCount1);
6168 2014 : GByte *pabyData2 = poFeature->GetFieldAsBinary(i, &nCount2);
6169 2014 : if (nCount1 != nCount2)
6170 2 : return FALSE;
6171 2012 : if (memcmp(pabyData1, pabyData2, nCount1) != 0)
6172 0 : return FALSE;
6173 2012 : break;
6174 : }
6175 :
6176 0 : default:
6177 0 : if (strcmp(GetFieldAsString(i),
6178 0 : poFeature->GetFieldAsString(i)) != 0)
6179 0 : return FALSE;
6180 0 : break;
6181 : }
6182 : }
6183 :
6184 3003 : const int nGeomFieldCount = GetGeomFieldCount();
6185 5702 : for (int i = 0; i < nGeomFieldCount; i++)
6186 : {
6187 2811 : const OGRGeometry *poThisGeom = GetGeomFieldRef(i);
6188 2811 : const OGRGeometry *poOtherGeom = poFeature->GetGeomFieldRef(i);
6189 :
6190 2811 : if (poThisGeom == nullptr && poOtherGeom != nullptr)
6191 3 : return FALSE;
6192 :
6193 2808 : if (poThisGeom != nullptr && poOtherGeom == nullptr)
6194 4 : return FALSE;
6195 :
6196 5428 : if (poThisGeom != nullptr && poOtherGeom != nullptr &&
6197 2624 : (!poThisGeom->Equals(poOtherGeom)))
6198 105 : return FALSE;
6199 : }
6200 :
6201 2891 : return TRUE;
6202 : }
6203 :
6204 : /************************************************************************/
6205 : /* OGR_F_Equal() */
6206 : /************************************************************************/
6207 :
6208 : /**
6209 : * \brief Test if two features are the same.
6210 : *
6211 : * Two features are considered equal if the share them (handle equality)
6212 : * same OGRFeatureDefn, have the same field values, and the same geometry
6213 : * (as tested by OGR_G_Equal()) as well as the same feature id.
6214 : *
6215 : * This function is the same as the C++ method OGRFeature::Equal().
6216 : *
6217 : * @param hFeat handle to one of the feature.
6218 : * @param hOtherFeat handle to the other feature to test this one against.
6219 : *
6220 : * @return TRUE if they are equal, otherwise FALSE.
6221 : */
6222 :
6223 109 : int OGR_F_Equal(OGRFeatureH hFeat, OGRFeatureH hOtherFeat)
6224 :
6225 : {
6226 109 : VALIDATE_POINTER1(hFeat, "OGR_F_Equal", 0);
6227 109 : VALIDATE_POINTER1(hOtherFeat, "OGR_F_Equal", 0);
6228 :
6229 218 : return OGRFeature::FromHandle(hFeat)->Equal(
6230 109 : OGRFeature::FromHandle(hOtherFeat));
6231 : }
6232 :
6233 : /************************************************************************/
6234 : /* SetFrom() */
6235 : /************************************************************************/
6236 :
6237 : /**
6238 : * \brief Set one feature from another.
6239 : *
6240 : * Overwrite the contents of this feature from the geometry and attributes
6241 : * of another. The poSrcFeature does not need to have the same
6242 : * OGRFeatureDefn. Field values are copied by corresponding field names.
6243 : * Field types do not have to exactly match. SetField() method conversion
6244 : * rules will be applied as needed.
6245 : *
6246 : * This method is the same as the C function OGR_F_SetFrom().
6247 : *
6248 : * @param poSrcFeature the feature from which geometry, and field values will
6249 : * be copied.
6250 : *
6251 : * @param bForgiving TRUE if the operation should continue despite lacking
6252 : * output fields matching some of the source fields.
6253 : *
6254 : * @return OGRERR_NONE if the operation succeeds, even if some values are
6255 : * not transferred, otherwise an error code.
6256 : */
6257 :
6258 5025 : OGRErr OGRFeature::SetFrom(const OGRFeature *poSrcFeature, int bForgiving)
6259 :
6260 : {
6261 5025 : const auto &oMap = poDefn->ComputeMapForSetFrom(poSrcFeature->GetDefnRef(),
6262 10050 : CPL_TO_BOOL(bForgiving));
6263 5025 : if (oMap.empty())
6264 : {
6265 274 : if (poSrcFeature->GetFieldCount())
6266 0 : return OGRERR_FAILURE;
6267 274 : int dummy = 0;
6268 274 : return SetFrom(poSrcFeature, &dummy, bForgiving);
6269 : }
6270 4751 : return SetFrom(poSrcFeature, oMap.data(), bForgiving);
6271 : }
6272 :
6273 : /************************************************************************/
6274 : /* OGR_F_SetFrom() */
6275 : /************************************************************************/
6276 :
6277 : /**
6278 : * \brief Set one feature from another.
6279 : *
6280 : * Overwrite the contents of this feature from the geometry and attributes
6281 : * of another. The hOtherFeature does not need to have the same
6282 : * OGRFeatureDefn. Field values are copied by corresponding field names.
6283 : * Field types do not have to exactly match. OGR_F_SetField*() function
6284 : * conversion rules will be applied as needed.
6285 : *
6286 : * This function is the same as the C++ method OGRFeature::SetFrom().
6287 : *
6288 : * @param hFeat handle to the feature to set to.
6289 : * @param hOtherFeat handle to the feature from which geometry,
6290 : * and field values will be copied.
6291 : *
6292 : * @param bForgiving TRUE if the operation should continue despite lacking
6293 : * output fields matching some of the source fields.
6294 : *
6295 : * @return OGRERR_NONE if the operation succeeds, even if some values are
6296 : * not transferred, otherwise an error code.
6297 : */
6298 :
6299 1812 : OGRErr OGR_F_SetFrom(OGRFeatureH hFeat, OGRFeatureH hOtherFeat, int bForgiving)
6300 :
6301 : {
6302 1812 : VALIDATE_POINTER1(hFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
6303 1812 : VALIDATE_POINTER1(hOtherFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
6304 :
6305 3624 : return OGRFeature::FromHandle(hFeat)->SetFrom(
6306 3624 : OGRFeature::FromHandle(hOtherFeat), bForgiving);
6307 : }
6308 :
6309 : /************************************************************************/
6310 : /* SetFrom() */
6311 : /************************************************************************/
6312 :
6313 : /**
6314 : * \brief Set one feature from another.
6315 : *
6316 : * Overwrite the contents of this feature from the geometry and attributes
6317 : * of another. The poSrcFeature does not need to have the same
6318 : * OGRFeatureDefn. Field values are copied according to the provided indices
6319 : * map. Field types do not have to exactly match. SetField() method
6320 : * conversion rules will be applied as needed. This is more efficient than
6321 : * OGR_F_SetFrom() in that this doesn't lookup the fields by their names.
6322 : * Particularly useful when the field names don't match.
6323 : *
6324 : * This method is the same as the C function OGR_F_SetFromWithMap().
6325 : *
6326 : * @param poSrcFeature the feature from which geometry, and field values will
6327 : * be copied.
6328 : *
6329 : * @param panMap Array of the indices of the feature's fields
6330 : * stored at the corresponding index of the source feature's fields. A value of
6331 : * -1 should be used to ignore the source's field. The array should not be NULL
6332 : * and be as long as the number of fields in the source feature.
6333 : *
6334 : * @param bForgiving TRUE if the operation should continue despite lacking
6335 : * output fields matching some of the source fields.
6336 : *
6337 : * @param bUseISO8601ForDateTimeAsString true if datetime fields
6338 : * converted to string should use ISO8601 formatting rather than OGR own format.
6339 : *
6340 : * @return OGRERR_NONE if the operation succeeds, even if some values are
6341 : * not transferred, otherwise an error code.
6342 : */
6343 :
6344 9502 : OGRErr OGRFeature::SetFrom(const OGRFeature *poSrcFeature, const int *panMap,
6345 : int bForgiving, bool bUseISO8601ForDateTimeAsString)
6346 :
6347 : {
6348 9502 : if (poSrcFeature == this)
6349 0 : return OGRERR_FAILURE;
6350 :
6351 9502 : SetFID(OGRNullFID);
6352 :
6353 : /* -------------------------------------------------------------------- */
6354 : /* Set the geometry. */
6355 : /* -------------------------------------------------------------------- */
6356 9502 : if (GetGeomFieldCount() == 1)
6357 : {
6358 8051 : const OGRGeomFieldDefn *poGFieldDefn = GetGeomFieldDefnRef(0);
6359 :
6360 8051 : int iSrc = poSrcFeature->GetGeomFieldIndex(poGFieldDefn->GetNameRef());
6361 8051 : if (iSrc >= 0)
6362 6596 : SetGeomField(0, poSrcFeature->GetGeomFieldRef(iSrc));
6363 : else
6364 : // Whatever the geometry field names are. For backward
6365 : // compatibility.
6366 1455 : SetGeomField(0, poSrcFeature->GetGeomFieldRef(0));
6367 : }
6368 : else
6369 : {
6370 2260 : for (int i = 0; i < GetGeomFieldCount(); i++)
6371 : {
6372 809 : const OGRGeomFieldDefn *poGFieldDefn = GetGeomFieldDefnRef(i);
6373 :
6374 : const int iSrc =
6375 809 : poSrcFeature->GetGeomFieldIndex(poGFieldDefn->GetNameRef());
6376 809 : if (iSrc >= 0)
6377 720 : SetGeomField(i, poSrcFeature->GetGeomFieldRef(iSrc));
6378 : else
6379 89 : SetGeomField(i, nullptr);
6380 : }
6381 : }
6382 :
6383 : /* -------------------------------------------------------------------- */
6384 : /* Copy feature style string. */
6385 : /* -------------------------------------------------------------------- */
6386 9502 : SetStyleString(poSrcFeature->GetStyleString());
6387 :
6388 : /* -------------------------------------------------------------------- */
6389 : /* Copy native data. */
6390 : /* -------------------------------------------------------------------- */
6391 9502 : SetNativeData(poSrcFeature->GetNativeData());
6392 9502 : SetNativeMediaType(poSrcFeature->GetNativeMediaType());
6393 :
6394 : /* -------------------------------------------------------------------- */
6395 : /* Set the fields by name. */
6396 : /* -------------------------------------------------------------------- */
6397 :
6398 9502 : const OGRErr eErr = SetFieldsFrom(poSrcFeature, panMap, bForgiving,
6399 : bUseISO8601ForDateTimeAsString);
6400 9502 : if (eErr != OGRERR_NONE)
6401 0 : return eErr;
6402 :
6403 9502 : return OGRERR_NONE;
6404 : }
6405 :
6406 : /************************************************************************/
6407 : /* OGR_F_SetFromWithMap() */
6408 : /************************************************************************/
6409 :
6410 : /**
6411 : * \brief Set one feature from another.
6412 : *
6413 : * Overwrite the contents of this feature from the geometry and attributes
6414 : * of another. The hOtherFeature does not need to have the same
6415 : * OGRFeatureDefn. Field values are copied according to the provided indices
6416 : * map. Field types do not have to exactly match. OGR_F_SetField*() function
6417 : * conversion rules will be applied as needed. This is more efficient than
6418 : * OGR_F_SetFrom() in that this doesn't lookup the fields by their names.
6419 : * Particularly useful when the field names don't match.
6420 : *
6421 : * This function is the same as the C++ method OGRFeature::SetFrom().
6422 : *
6423 : * @param hFeat handle to the feature to set to.
6424 : * @param hOtherFeat handle to the feature from which geometry,
6425 : * and field values will be copied.
6426 : *
6427 : * @param panMap Array of the indices of the destination feature's fields
6428 : * stored at the corresponding index of the source feature's fields. A value of
6429 : * -1 should be used to ignore the source's field. The array should not be NULL
6430 : * and be as long as the number of fields in the source feature.
6431 : *
6432 : * @param bForgiving TRUE if the operation should continue despite lacking
6433 : * output fields matching some of the source fields.
6434 : *
6435 : * @return OGRERR_NONE if the operation succeeds, even if some values are
6436 : * not transferred, otherwise an error code.
6437 : */
6438 :
6439 10 : OGRErr OGR_F_SetFromWithMap(OGRFeatureH hFeat, OGRFeatureH hOtherFeat,
6440 : int bForgiving, const int *panMap)
6441 :
6442 : {
6443 10 : VALIDATE_POINTER1(hFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
6444 10 : VALIDATE_POINTER1(hOtherFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
6445 10 : VALIDATE_POINTER1(panMap, "OGR_F_SetFrom", OGRERR_FAILURE);
6446 :
6447 20 : return OGRFeature::FromHandle(hFeat)->SetFrom(
6448 20 : OGRFeature::FromHandle(hOtherFeat), panMap, bForgiving);
6449 : }
6450 :
6451 : /************************************************************************/
6452 : /* SetFieldsFrom() */
6453 : /************************************************************************/
6454 :
6455 : /**
6456 : * \brief Set fields from another feature.
6457 : *
6458 : * Overwrite the fields of this feature from the attributes of
6459 : * another. The FID and the style string are not set. The poSrcFeature
6460 : * does not need to have the same OGRFeatureDefn. Field values are
6461 : * copied according to the provided indices map. Field types do not
6462 : * have to exactly match. SetField() method conversion rules will be
6463 : * applied as needed. This is more efficient than OGR_F_SetFrom() in
6464 : * that this doesn't lookup the fields by their names. Particularly
6465 : * useful when the field names don't match.
6466 : *
6467 : * @param poSrcFeature the feature from which geometry, and field values will
6468 : * be copied.
6469 : *
6470 : * @param panMap Array of the indices of the feature's fields
6471 : * stored at the corresponding index of the source feature's fields. A value of
6472 : * -1 should be used to ignore the source's field. The array should not be NULL
6473 : * and be as long as the number of fields in the source feature.
6474 : *
6475 : * @param bForgiving TRUE if the operation should continue despite lacking
6476 : * output fields matching some of the source fields.
6477 : *
6478 : * @param bUseISO8601ForDateTimeAsString true if datetime fields
6479 : * converted to string should use ISO8601 formatting rather than OGR own format.
6480 : *
6481 : * @return OGRERR_NONE if the operation succeeds, even if some values are
6482 : * not transferred, otherwise an error code.
6483 : */
6484 :
6485 11382 : OGRErr OGRFeature::SetFieldsFrom(const OGRFeature *poSrcFeature,
6486 : const int *panMap, int bForgiving,
6487 : bool bUseISO8601ForDateTimeAsString)
6488 :
6489 : {
6490 11382 : const int nSrcFieldCount = poSrcFeature->poDefn->GetFieldCountUnsafe();
6491 11382 : const int nFieldCount = poDefn->GetFieldCountUnsafe();
6492 118384 : for (int iField = 0; iField < nSrcFieldCount; iField++)
6493 : {
6494 107002 : const int iDstField = panMap[iField];
6495 :
6496 107002 : if (iDstField < 0)
6497 3704 : continue;
6498 :
6499 103298 : if (nFieldCount <= iDstField)
6500 0 : return OGRERR_FAILURE;
6501 :
6502 103298 : if (!poSrcFeature->IsFieldSetUnsafe(iField))
6503 : {
6504 9476 : UnsetField(iDstField);
6505 9476 : continue;
6506 : }
6507 :
6508 93822 : if (poSrcFeature->IsFieldNullUnsafe(iField))
6509 : {
6510 1751 : SetFieldNull(iDstField);
6511 1751 : continue;
6512 : }
6513 :
6514 : const auto eSrcType =
6515 92071 : poSrcFeature->poDefn->GetFieldDefnUnsafe(iField)->GetType();
6516 92071 : const auto eDstType = poDefn->GetFieldDefnUnsafe(iDstField)->GetType();
6517 92071 : if (eSrcType == eDstType)
6518 : {
6519 89018 : if (eSrcType == OFTInteger)
6520 : {
6521 30749 : SetFieldSameTypeUnsafe(
6522 : iDstField, poSrcFeature->GetFieldAsIntegerUnsafe(iField));
6523 30749 : continue;
6524 : }
6525 58269 : if (eSrcType == OFTInteger64)
6526 : {
6527 3441 : SetFieldSameTypeUnsafe(
6528 : iDstField, poSrcFeature->GetFieldAsInteger64Unsafe(iField));
6529 3441 : continue;
6530 : }
6531 54828 : if (eSrcType == OFTReal)
6532 : {
6533 13487 : SetFieldSameTypeUnsafe(
6534 : iDstField, poSrcFeature->GetFieldAsDoubleUnsafe(iField));
6535 13487 : continue;
6536 : }
6537 41341 : if (eSrcType == OFTString)
6538 : {
6539 40552 : if (IsFieldSetAndNotNullUnsafe(iDstField))
6540 1505 : CPLFree(pauFields[iDstField].String);
6541 :
6542 40552 : SetFieldSameTypeUnsafe(
6543 : iDstField,
6544 : VSI_STRDUP_VERBOSE(
6545 : poSrcFeature->GetFieldAsStringUnsafe(iField)));
6546 40552 : continue;
6547 : }
6548 : }
6549 :
6550 : // Check if we must convert list types to JSON
6551 3842 : if (eDstType == OFTString)
6552 : {
6553 : const auto eDstSubType =
6554 61 : poDefn->GetFieldDefnUnsafe(iDstField)->GetSubType();
6555 61 : if (eDstSubType == OFSTJSON &&
6556 17 : (eSrcType == OFTIntegerList || eSrcType == OFTInteger64List ||
6557 6 : eSrcType == OFTRealList || eSrcType == OFTStringList))
6558 : {
6559 26 : char *pszVal = poSrcFeature->GetFieldAsSerializedJSon(iField);
6560 26 : if (pszVal)
6561 : {
6562 26 : SetField(iDstField, pszVal);
6563 26 : CPLFree(pszVal);
6564 26 : continue;
6565 : }
6566 : }
6567 : }
6568 :
6569 3816 : switch (eSrcType)
6570 : {
6571 1205 : case OFTInteger:
6572 1205 : SetField(iDstField,
6573 : poSrcFeature->GetFieldAsIntegerUnsafe(iField));
6574 1205 : break;
6575 :
6576 1613 : case OFTInteger64:
6577 1613 : SetField(iDstField,
6578 : poSrcFeature->GetFieldAsInteger64Unsafe(iField));
6579 1613 : break;
6580 :
6581 25 : case OFTReal:
6582 25 : SetField(iDstField,
6583 : poSrcFeature->GetFieldAsDoubleUnsafe(iField));
6584 25 : break;
6585 :
6586 86 : case OFTString:
6587 86 : SetField(iDstField,
6588 : poSrcFeature->GetFieldAsStringUnsafe(iField));
6589 86 : break;
6590 :
6591 270 : case OFTIntegerList:
6592 : {
6593 270 : if (eDstType == OFTString)
6594 : {
6595 2 : SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
6596 : }
6597 : else
6598 : {
6599 268 : int nCount = 0;
6600 : const int *panValues =
6601 268 : poSrcFeature->GetFieldAsIntegerList(iField, &nCount);
6602 268 : SetField(iDstField, nCount, panValues);
6603 : }
6604 : }
6605 270 : break;
6606 :
6607 47 : case OFTInteger64List:
6608 : {
6609 47 : if (eDstType == OFTString)
6610 : {
6611 1 : SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
6612 : }
6613 : else
6614 : {
6615 46 : int nCount = 0;
6616 : const GIntBig *panValues =
6617 46 : poSrcFeature->GetFieldAsInteger64List(iField, &nCount);
6618 46 : SetField(iDstField, nCount, panValues);
6619 : }
6620 : }
6621 47 : break;
6622 :
6623 86 : case OFTRealList:
6624 : {
6625 86 : if (eDstType == OFTString)
6626 : {
6627 2 : SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
6628 : }
6629 : else
6630 : {
6631 84 : int nCount = 0;
6632 : const double *padfValues =
6633 84 : poSrcFeature->GetFieldAsDoubleList(iField, &nCount);
6634 84 : SetField(iDstField, nCount, padfValues);
6635 : }
6636 : }
6637 86 : break;
6638 :
6639 412 : case OFTDate:
6640 : case OFTDateTime:
6641 : case OFTTime:
6642 : {
6643 412 : if (eDstType == OFTDate || eDstType == OFTTime ||
6644 : eDstType == OFTDateTime)
6645 : {
6646 380 : SetField(iDstField, poSrcFeature->GetRawFieldRef(iField));
6647 : }
6648 32 : else if (eDstType == OFTString || eDstType == OFTStringList)
6649 : {
6650 22 : SetField(iDstField,
6651 4 : eSrcType == OFTDateTime &&
6652 : bUseISO8601ForDateTimeAsString
6653 2 : ? poSrcFeature->GetFieldAsISO8601DateTime(
6654 : iField, nullptr)
6655 9 : : poSrcFeature->GetFieldAsString(iField));
6656 : }
6657 21 : else if (!bForgiving)
6658 0 : return OGRERR_FAILURE;
6659 412 : break;
6660 : }
6661 :
6662 72 : default:
6663 : {
6664 72 : if (eSrcType == eDstType)
6665 : {
6666 47 : SetField(iDstField, poSrcFeature->GetRawFieldRef(iField));
6667 : }
6668 25 : else if (eDstType == OFTString || eDstType == OFTStringList)
6669 : {
6670 6 : SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
6671 : }
6672 19 : else if (!bForgiving)
6673 0 : return OGRERR_FAILURE;
6674 72 : break;
6675 : }
6676 : }
6677 : }
6678 :
6679 11382 : return OGRERR_NONE;
6680 : }
6681 :
6682 : /************************************************************************/
6683 : /* GetStyleString() */
6684 : /************************************************************************/
6685 :
6686 : /**
6687 : * \brief Fetch style string for this feature.
6688 : *
6689 : * Set the OGR Feature Style Specification for details on the format of
6690 : * this string, and ogr_featurestyle.h for services available to parse it.
6691 : *
6692 : * This method is the same as the C function OGR_F_GetStyleString().
6693 : *
6694 : * @return a reference to a representation in string format, or NULL if
6695 : * there isn't one.
6696 : */
6697 :
6698 61489 : const char *OGRFeature::GetStyleString() const
6699 : {
6700 61489 : if (m_pszStyleString)
6701 8731 : return m_pszStyleString;
6702 :
6703 52758 : const int iStyleFieldIndex = GetFieldIndex("OGR_STYLE");
6704 52758 : if (iStyleFieldIndex >= 0)
6705 62 : return GetFieldAsString(iStyleFieldIndex);
6706 :
6707 52696 : return nullptr;
6708 : }
6709 :
6710 : /************************************************************************/
6711 : /* OGR_F_GetStyleString() */
6712 : /************************************************************************/
6713 :
6714 : /**
6715 : * \brief Fetch style string for this feature.
6716 : *
6717 : * Set the OGR Feature Style Specification for details on the format of
6718 : * this string, and ogr_featurestyle.h for services available to parse it.
6719 : *
6720 : * This function is the same as the C++ method OGRFeature::GetStyleString().
6721 : *
6722 : * @param hFeat handle to the feature to get the style from.
6723 : * @return a reference to a representation in string format, or NULL if
6724 : * there isn't one.
6725 : */
6726 :
6727 1585 : const char *OGR_F_GetStyleString(OGRFeatureH hFeat)
6728 : {
6729 1585 : VALIDATE_POINTER1(hFeat, "OGR_F_GetStyleString", nullptr);
6730 :
6731 1585 : return OGRFeature::FromHandle(hFeat)->GetStyleString();
6732 : }
6733 :
6734 : /************************************************************************/
6735 : /* SetStyleString() */
6736 : /************************************************************************/
6737 :
6738 : /**
6739 : * \brief Set feature style string.
6740 : *
6741 : * This method operates the same as OGRFeature::SetStyleStringDirectly() except
6742 : * that it does not assume ownership of the passed string, but instead makes a
6743 : * copy of it.
6744 : *
6745 : * This method is the same as the C function OGR_F_SetStyleString().
6746 : *
6747 : * @param pszString the style string to apply to this feature, cannot be NULL.
6748 : */
6749 :
6750 339338 : void OGRFeature::SetStyleString(const char *pszString)
6751 : {
6752 339338 : if (m_pszStyleString)
6753 : {
6754 2364 : CPLFree(m_pszStyleString);
6755 2364 : m_pszStyleString = nullptr;
6756 : }
6757 :
6758 339338 : if (pszString)
6759 324476 : m_pszStyleString = VSI_STRDUP_VERBOSE(pszString);
6760 339338 : }
6761 :
6762 : /************************************************************************/
6763 : /* OGR_F_SetStyleString() */
6764 : /************************************************************************/
6765 :
6766 : /**
6767 : * \brief Set feature style string.
6768 : *
6769 : * This method operates the same as OGR_F_SetStyleStringDirectly() except that it
6770 : * does not assume ownership of the passed string, but instead makes a copy of
6771 : * it.
6772 : *
6773 : * This function is the same as the C++ method OGRFeature::SetStyleString().
6774 : *
6775 : * @param hFeat handle to the feature to set style to.
6776 : * @param pszStyle the style string to apply to this feature, cannot be NULL.
6777 : */
6778 :
6779 89 : void OGR_F_SetStyleString(OGRFeatureH hFeat, const char *pszStyle)
6780 :
6781 : {
6782 89 : VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleString");
6783 :
6784 89 : OGRFeature::FromHandle(hFeat)->SetStyleString(pszStyle);
6785 : }
6786 :
6787 : /************************************************************************/
6788 : /* SetStyleStringDirectly() */
6789 : /************************************************************************/
6790 :
6791 : /**
6792 : * \brief Set feature style string.
6793 : *
6794 : * This method operates the same as OGRFeature::SetStyleString() except that it
6795 : * assumes ownership of the passed string.
6796 : *
6797 : * This method is the same as the C function OGR_F_SetStyleStringDirectly().
6798 : *
6799 : * @param pszString the style string to apply to this feature, cannot be NULL.
6800 : */
6801 :
6802 0 : void OGRFeature::SetStyleStringDirectly(char *pszString)
6803 : {
6804 0 : CPLFree(m_pszStyleString);
6805 0 : m_pszStyleString = pszString;
6806 0 : }
6807 :
6808 : /************************************************************************/
6809 : /* OGR_F_SetStyleStringDirectly() */
6810 : /************************************************************************/
6811 :
6812 : /**
6813 : * \brief Set feature style string.
6814 : *
6815 : * This method operates the same as OGR_F_SetStyleString() except that it assumes
6816 : * ownership of the passed string.
6817 : *
6818 : * This function is the same as the C++ method
6819 : * OGRFeature::SetStyleStringDirectly().
6820 : *
6821 : * @param hFeat handle to the feature to set style to.
6822 : * @param pszStyle the style string to apply to this feature, cannot be NULL.
6823 : */
6824 :
6825 0 : void OGR_F_SetStyleStringDirectly(OGRFeatureH hFeat, char *pszStyle)
6826 :
6827 : {
6828 0 : VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleStringDirectly");
6829 :
6830 0 : OGRFeature::FromHandle(hFeat)->SetStyleStringDirectly(pszStyle);
6831 : }
6832 :
6833 : //************************************************************************/
6834 : /* SetStyleTable() */
6835 : /************************************************************************/
6836 :
6837 : /** Set style table.
6838 : * @param poStyleTable new style table (will be cloned)
6839 : */
6840 0 : void OGRFeature::SetStyleTable(OGRStyleTable *poStyleTable)
6841 : {
6842 0 : if (m_poStyleTable)
6843 0 : delete m_poStyleTable;
6844 0 : m_poStyleTable = poStyleTable ? poStyleTable->Clone() : nullptr;
6845 0 : }
6846 :
6847 : //************************************************************************/
6848 : /* SetStyleTableDirectly() */
6849 : /************************************************************************/
6850 :
6851 : /** Set style table.
6852 : * @param poStyleTable new style table (ownership transferred to the object)
6853 : */
6854 0 : void OGRFeature::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
6855 : {
6856 0 : if (m_poStyleTable)
6857 0 : delete m_poStyleTable;
6858 0 : m_poStyleTable = poStyleTable;
6859 0 : }
6860 :
6861 : //! @cond Doxygen_Suppress
6862 :
6863 : /************************************************************************/
6864 : /* RemapFields() */
6865 : /* */
6866 : /* This is used to transform a feature "in place" from one */
6867 : /* feature defn to another with minimum work. */
6868 : /************************************************************************/
6869 :
6870 50 : OGRErr OGRFeature::RemapFields(const OGRFeatureDefn *poNewDefn,
6871 : const int *panRemapSource)
6872 :
6873 : {
6874 50 : if (poNewDefn == nullptr)
6875 50 : poNewDefn = poDefn;
6876 :
6877 50 : const int nNewFieldCount = poNewDefn->GetFieldCount();
6878 : OGRField *pauNewFields =
6879 50 : static_cast<OGRField *>(CPLCalloc(nNewFieldCount, sizeof(OGRField)));
6880 :
6881 50 : const int nFieldCount = poDefn->GetFieldCount();
6882 318 : for (int iDstField = 0; iDstField < nFieldCount; iDstField++)
6883 : {
6884 268 : if (panRemapSource[iDstField] == -1)
6885 : {
6886 16 : OGR_RawField_SetUnset(&pauNewFields[iDstField]);
6887 : }
6888 : else
6889 : {
6890 252 : memcpy(pauNewFields + iDstField,
6891 252 : pauFields + panRemapSource[iDstField], sizeof(OGRField));
6892 : }
6893 : }
6894 :
6895 : // We really should be freeing memory for old columns that
6896 : // are no longer present. We don't for now because it is a bit messy
6897 : // and would take too long to test.
6898 :
6899 : /* -------------------------------------------------------------------- */
6900 : /* Apply new definition and fields. */
6901 : /* -------------------------------------------------------------------- */
6902 50 : CPLFree(pauFields);
6903 50 : pauFields = pauNewFields;
6904 :
6905 50 : poDefn = poNewDefn;
6906 :
6907 50 : return OGRERR_NONE;
6908 : }
6909 :
6910 : /************************************************************************/
6911 : /* AppendField() */
6912 : /* */
6913 : /* This is used to transform a feature "in place" by appending */
6914 : /* an unset field. */
6915 : /************************************************************************/
6916 :
6917 573 : void OGRFeature::AppendField()
6918 : {
6919 573 : const int nFieldCount = poDefn->GetFieldCountUnsafe();
6920 573 : pauFields = static_cast<OGRField *>(
6921 573 : CPLRealloc(pauFields, nFieldCount * sizeof(OGRField)));
6922 573 : OGR_RawField_SetUnset(&pauFields[nFieldCount - 1]);
6923 573 : }
6924 :
6925 : /************************************************************************/
6926 : /* RemapGeomFields() */
6927 : /* */
6928 : /* This is used to transform a feature "in place" from one */
6929 : /* feature defn to another with minimum work. */
6930 : /************************************************************************/
6931 :
6932 3 : OGRErr OGRFeature::RemapGeomFields(const OGRFeatureDefn *poNewDefn,
6933 : const int *panRemapSource)
6934 :
6935 : {
6936 3 : if (poNewDefn == nullptr)
6937 3 : poNewDefn = poDefn;
6938 :
6939 : OGRGeometry **papoNewGeomFields = static_cast<OGRGeometry **>(
6940 3 : CPLCalloc(poNewDefn->GetGeomFieldCount(), sizeof(OGRGeometry *)));
6941 :
6942 9 : for (int iDstField = 0; iDstField < poDefn->GetGeomFieldCount();
6943 : iDstField++)
6944 : {
6945 6 : if (panRemapSource[iDstField] == -1)
6946 : {
6947 3 : papoNewGeomFields[iDstField] = nullptr;
6948 : }
6949 : else
6950 : {
6951 3 : papoNewGeomFields[iDstField] =
6952 3 : papoGeometries[panRemapSource[iDstField]];
6953 : }
6954 : }
6955 :
6956 : // We really should be freeing memory for old columns that
6957 : // are no longer present. We don't for now because it is a bit messy
6958 : // and would take too long to test.
6959 :
6960 : /* -------------------------------------------------------------------- */
6961 : /* Apply new definition and fields. */
6962 : /* -------------------------------------------------------------------- */
6963 3 : CPLFree(papoGeometries);
6964 3 : papoGeometries = papoNewGeomFields;
6965 :
6966 3 : poDefn = poNewDefn;
6967 :
6968 3 : return OGRERR_NONE;
6969 : }
6970 :
6971 : //! @endcond
6972 :
6973 : /************************************************************************/
6974 : /* OGR_F_GetStyleTable() */
6975 : /************************************************************************/
6976 :
6977 0 : OGRStyleTableH OGR_F_GetStyleTable(OGRFeatureH hFeat)
6978 :
6979 : {
6980 0 : VALIDATE_POINTER1(hFeat, "OGR_F_GetStyleTable", nullptr);
6981 :
6982 : return reinterpret_cast<OGRStyleTableH>(
6983 0 : OGRFeature::FromHandle(hFeat)->GetStyleTable());
6984 : }
6985 :
6986 : /************************************************************************/
6987 : /* OGR_F_SetStyleTableDirectly() */
6988 : /************************************************************************/
6989 :
6990 0 : void OGR_F_SetStyleTableDirectly(OGRFeatureH hFeat, OGRStyleTableH hStyleTable)
6991 :
6992 : {
6993 0 : VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleTableDirectly");
6994 :
6995 0 : OGRFeature::FromHandle(hFeat)->SetStyleTableDirectly(
6996 0 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
6997 : }
6998 :
6999 : /************************************************************************/
7000 : /* OGR_F_SetStyleTable() */
7001 : /************************************************************************/
7002 :
7003 0 : void OGR_F_SetStyleTable(OGRFeatureH hFeat, OGRStyleTableH hStyleTable)
7004 :
7005 : {
7006 0 : VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleTable");
7007 0 : VALIDATE_POINTER0(hStyleTable, "OGR_F_SetStyleTable");
7008 :
7009 0 : OGRFeature::FromHandle(hFeat)->SetStyleTable(
7010 0 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
7011 : }
7012 :
7013 : /************************************************************************/
7014 : /* FillUnsetWithDefault() */
7015 : /************************************************************************/
7016 :
7017 : /**
7018 : * \brief Fill unset fields with default values that might be defined.
7019 : *
7020 : * This method is the same as the C function OGR_F_FillUnsetWithDefault().
7021 : *
7022 : * @param bNotNullableOnly if we should fill only unset fields with a not-null
7023 : * constraint.
7024 : * @param papszOptions unused currently. Must be set to NULL.
7025 : */
7026 :
7027 277817 : void OGRFeature::FillUnsetWithDefault(int bNotNullableOnly,
7028 : CPL_UNUSED CSLConstList papszOptions)
7029 : {
7030 277817 : const int nFieldCount = poDefn->GetFieldCount();
7031 4756340 : for (int i = 0; i < nFieldCount; i++)
7032 : {
7033 4478520 : if (IsFieldSetUnsafe(i))
7034 4476970 : continue;
7035 1557 : const auto poFieldDefn = poDefn->GetFieldDefn(i);
7036 1557 : if (bNotNullableOnly && poFieldDefn->IsNullable())
7037 109 : continue;
7038 1448 : const char *pszDefault = poFieldDefn->GetDefault();
7039 1448 : OGRFieldType eType = poFieldDefn->GetType();
7040 1448 : if (pszDefault != nullptr)
7041 : {
7042 48 : if (eType == OFTDate || eType == OFTTime || eType == OFTDateTime)
7043 : {
7044 9 : if (STARTS_WITH_CI(pszDefault, "CURRENT"))
7045 : {
7046 4 : time_t t = time(nullptr);
7047 : struct tm brokendown;
7048 4 : CPLUnixTimeToYMDHMS(t, &brokendown);
7049 4 : SetField(i, brokendown.tm_year + 1900,
7050 4 : brokendown.tm_mon + 1, brokendown.tm_mday,
7051 : brokendown.tm_hour, brokendown.tm_min,
7052 4 : static_cast<float>(brokendown.tm_sec), 100);
7053 : }
7054 : else
7055 : {
7056 5 : int nYear = 0;
7057 5 : int nMonth = 0;
7058 5 : int nDay = 0;
7059 5 : int nHour = 0;
7060 5 : int nMinute = 0;
7061 5 : float fSecond = 0.0f;
7062 5 : if (sscanf(pszDefault, "'%d/%d/%d %d:%d:%f'", &nYear,
7063 5 : &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6)
7064 : {
7065 4 : SetField(i, nYear, nMonth, nDay, nHour, nMinute,
7066 : fSecond, 100);
7067 : }
7068 9 : }
7069 : }
7070 39 : else if (eType == OFTString && pszDefault[0] == '\'' &&
7071 8 : pszDefault[strlen(pszDefault) - 1] == '\'')
7072 : {
7073 16 : CPLString osDefault(pszDefault + 1);
7074 8 : osDefault.pop_back();
7075 8 : char *pszTmp = CPLUnescapeString(osDefault, nullptr, CPLES_SQL);
7076 8 : SetField(i, pszTmp);
7077 16 : CPLFree(pszTmp);
7078 : }
7079 31 : else if (!poFieldDefn->IsDefaultDriverSpecific())
7080 13 : SetField(i, pszDefault);
7081 : }
7082 : }
7083 277817 : }
7084 :
7085 : /************************************************************************/
7086 : /* OGR_F_FillUnsetWithDefault() */
7087 : /************************************************************************/
7088 :
7089 : /**
7090 : * \brief Fill unset fields with default values that might be defined.
7091 : *
7092 : * This function is the same as the C++ method
7093 : * OGRFeature::FillUnsetWithDefault().
7094 : *
7095 : * @param hFeat handle to the feature.
7096 : * @param bNotNullableOnly if we should fill only unset fields with a not-null
7097 : * constraint.
7098 : * @param papszOptions unused currently. Must be set to NULL.
7099 : */
7100 :
7101 2 : void OGR_F_FillUnsetWithDefault(OGRFeatureH hFeat, int bNotNullableOnly,
7102 : CSLConstList papszOptions)
7103 :
7104 : {
7105 2 : VALIDATE_POINTER0(hFeat, "OGR_F_FillUnsetWithDefault");
7106 :
7107 2 : OGRFeature::FromHandle(hFeat)->FillUnsetWithDefault(bNotNullableOnly,
7108 : papszOptions);
7109 : }
7110 :
7111 : /************************************************************************/
7112 : /* Validate() */
7113 : /************************************************************************/
7114 :
7115 : /**
7116 : * \brief Validate that a feature meets constraints of its schema.
7117 : *
7118 : * The scope of test is specified with the nValidateFlags parameter.
7119 : *
7120 : * Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width must be
7121 : * interpreted as the number of UTF-8 characters. Some drivers might interpret
7122 : * the width as the number of bytes instead. So this test is rather conservative
7123 : * (if it fails, then it will fail for all interpretations).
7124 : *
7125 : * This method is the same as the C function OGR_F_Validate().
7126 : *
7127 : * @param nValidateFlags OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
7128 : * OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and
7129 : * OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT,
7130 : * OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM with '|' operator
7131 : * @param bEmitError TRUE if a CPLError() must be emitted when a check fails
7132 : * @return TRUE if all enabled validation tests pass.
7133 : */
7134 :
7135 470 : int OGRFeature::Validate(int nValidateFlags, int bEmitError) const
7136 :
7137 : {
7138 470 : bool bRet = true;
7139 :
7140 470 : const int nGeomFieldCount = poDefn->GetGeomFieldCount();
7141 900 : for (int i = 0; i < nGeomFieldCount; i++)
7142 : {
7143 430 : if ((nValidateFlags & OGR_F_VAL_NULL) &&
7144 860 : !poDefn->GetGeomFieldDefn(i)->IsNullable() &&
7145 12 : GetGeomFieldRef(i) == nullptr)
7146 : {
7147 3 : bRet = false;
7148 3 : if (bEmitError)
7149 : {
7150 3 : CPLError(
7151 : CE_Failure, CPLE_AppDefined,
7152 : "Geometry field %s has a NULL content which is not allowed",
7153 3 : poDefn->GetGeomFieldDefn(i)->GetNameRef());
7154 : }
7155 : }
7156 603 : if ((nValidateFlags & OGR_F_VAL_GEOM_TYPE) &&
7157 173 : poDefn->GetGeomFieldDefn(i)->GetType() != wkbUnknown)
7158 : {
7159 136 : const OGRGeometry *poGeom = GetGeomFieldRef(i);
7160 136 : if (poGeom != nullptr)
7161 : {
7162 : const OGRwkbGeometryType eType =
7163 101 : poDefn->GetGeomFieldDefn(i)->GetType();
7164 101 : const OGRwkbGeometryType eFType = poGeom->getGeometryType();
7165 200 : if ((nValidateFlags & OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM) &&
7166 99 : (wkbFlatten(eFType) == wkbFlatten(eType) ||
7167 17 : wkbFlatten(eType) == wkbUnknown))
7168 : {
7169 : // Ok.
7170 : }
7171 32 : else if ((eType == wkbSetZ(wkbUnknown) && !wkbHasZ(eFType)) ||
7172 16 : (eType != wkbSetZ(wkbUnknown) && eFType != eType))
7173 : {
7174 15 : bRet = false;
7175 15 : if (bEmitError)
7176 : {
7177 30 : CPLError(CE_Failure, CPLE_AppDefined,
7178 : "Geometry field %s has a %s geometry whereas "
7179 : "%s is expected",
7180 15 : poDefn->GetGeomFieldDefn(i)->GetNameRef(),
7181 : OGRGeometryTypeToName(eFType),
7182 : OGRGeometryTypeToName(eType));
7183 : }
7184 : }
7185 : }
7186 : }
7187 : }
7188 470 : const int nFieldCount = poDefn->GetFieldCount();
7189 1670 : for (int i = 0; i < nFieldCount; i++)
7190 : {
7191 1200 : if ((nValidateFlags & OGR_F_VAL_NULL) &&
7192 2403 : !poDefn->GetFieldDefn(i)->IsNullable() && !IsFieldSet(i) &&
7193 3 : (!(nValidateFlags & OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT) ||
7194 2 : poDefn->GetFieldDefn(i)->GetDefault() == nullptr))
7195 : {
7196 3 : bRet = false;
7197 3 : if (bEmitError)
7198 : {
7199 6 : CPLError(CE_Failure, CPLE_AppDefined,
7200 : "Field %s.%s has a NULL content which is not allowed",
7201 3 : poDefn->GetName(),
7202 3 : poDefn->GetFieldDefn(i)->GetNameRef());
7203 : }
7204 : }
7205 630 : if ((nValidateFlags & OGR_F_VAL_WIDTH) &&
7206 866 : poDefn->GetFieldDefn(i)->GetWidth() > 0 &&
7207 308 : poDefn->GetFieldDefn(i)->GetType() == OFTString && IsFieldSet(i) &&
7208 1902 : CPLIsUTF8(GetFieldAsString(i), -1) &&
7209 72 : CPLStrlenUTF8Ex(GetFieldAsString(i)) >
7210 72 : static_cast<size_t>(poDefn->GetFieldDefn(i)->GetWidth()))
7211 : {
7212 1 : bRet = false;
7213 1 : if (bEmitError)
7214 : {
7215 3 : CPLError(
7216 : CE_Failure, CPLE_AppDefined,
7217 : "Field %s.%s has %" PRIu64 " UTF-8 characters whereas "
7218 : "a maximum of %d is allowed",
7219 1 : poDefn->GetName(), poDefn->GetFieldDefn(i)->GetNameRef(),
7220 1 : static_cast<uint64_t>(CPLStrlenUTF8Ex(GetFieldAsString(i))),
7221 1 : poDefn->GetFieldDefn(i)->GetWidth());
7222 : }
7223 : }
7224 : }
7225 :
7226 470 : return bRet;
7227 : }
7228 :
7229 : /************************************************************************/
7230 : /* OGR_F_Validate() */
7231 : /************************************************************************/
7232 :
7233 : /**
7234 : * \brief Validate that a feature meets constraints of its schema.
7235 : *
7236 : * The scope of test is specified with the nValidateFlags parameter.
7237 : *
7238 : * Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width must be
7239 : * interpreted as the number of UTF-8 characters. Some drivers might interpret
7240 : * the width as the number of bytes instead. So this test is rather conservative
7241 : * (if it fails, then it will fail for all interpretations).
7242 : *
7243 : * This function is the same as the C++ method
7244 : * OGRFeature::Validate().
7245 : *
7246 : * @param hFeat handle to the feature to validate.
7247 : * @param nValidateFlags OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
7248 : * OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and
7249 : * OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT with '|' operator
7250 : * @param bEmitError TRUE if a CPLError() must be emitted when a check fails
7251 : * @return TRUE if all enabled validation tests pass.
7252 : */
7253 :
7254 10 : int OGR_F_Validate(OGRFeatureH hFeat, int nValidateFlags, int bEmitError)
7255 :
7256 : {
7257 10 : VALIDATE_POINTER1(hFeat, "OGR_F_Validate", FALSE);
7258 :
7259 10 : return OGRFeature::FromHandle(hFeat)->Validate(nValidateFlags, bEmitError);
7260 : }
7261 :
7262 : /************************************************************************/
7263 : /* GetNativeData() */
7264 : /************************************************************************/
7265 :
7266 : /**
7267 : * \fn const char* OGRFeature::GetNativeData() const;
7268 : *
7269 : * \brief Returns the native data for the feature.
7270 : *
7271 : * The native data is the representation in a "natural" form that comes from
7272 : * the driver that created this feature, or that is aimed at an output driver.
7273 : * The native data may be in different format, which is indicated by
7274 : * GetNativeMediaType().
7275 : *
7276 : * Note that most drivers do not support storing the native data in the feature
7277 : * object, and if they do, generally the NATIVE_DATA open option must be passed
7278 : * at dataset opening.
7279 : *
7280 : * The "native data" does not imply it is something more performant or powerful
7281 : * than what can be obtained with the rest of the API, but it may be useful in
7282 : * round-tripping scenarios where some characteristics of the underlying format
7283 : * are not captured otherwise by the OGR abstraction.
7284 : *
7285 : * This function is the same as the C function
7286 : * OGR_F_GetNativeData().
7287 : *
7288 : * @return a string with the native data, or NULL if there is none.
7289 : *
7290 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7291 : */
7292 :
7293 : /************************************************************************/
7294 : /* OGR_F_GetNativeData() */
7295 : /************************************************************************/
7296 :
7297 : /**
7298 : * \brief Returns the native data for the feature.
7299 : *
7300 : * The native data is the representation in a "natural" form that comes from
7301 : * the driver that created this feature, or that is aimed at an output driver.
7302 : * The native data may be in different format, which is indicated by
7303 : * OGR_F_GetNativeMediaType().
7304 : *
7305 : * Note that most drivers do not support storing the native data in the feature
7306 : * object, and if they do, generally the NATIVE_DATA open option must be passed
7307 : * at dataset opening.
7308 : *
7309 : * The "native data" does not imply it is something more performant or powerful
7310 : * than what can be obtained with the rest of the API, but it may be useful in
7311 : * round-tripping scenarios where some characteristics of the underlying format
7312 : * are not captured otherwise by the OGR abstraction.
7313 : *
7314 : * This function is the same as the C++ method
7315 : * OGRFeature::GetNativeData().
7316 : *
7317 : * @param hFeat handle to the feature.
7318 : * @return a string with the native data, or NULL if there is none.
7319 : *
7320 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7321 : */
7322 :
7323 9 : const char *OGR_F_GetNativeData(OGRFeatureH hFeat)
7324 :
7325 : {
7326 9 : VALIDATE_POINTER1(hFeat, "OGR_F_GetNativeData", nullptr);
7327 :
7328 9 : return OGRFeature::FromHandle(hFeat)->GetNativeData();
7329 : }
7330 :
7331 : /************************************************************************/
7332 : /* GetNativeMediaType() */
7333 : /************************************************************************/
7334 :
7335 : /**
7336 : * \fn const char* OGRFeature::GetNativeMediaType() const;
7337 : *
7338 : * \brief Returns the native media type for the feature.
7339 : *
7340 : * The native media type is the identifier for the format of the native data.
7341 : * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
7342 : * e.g. "application/vnd.geo+json" for JSon.
7343 : *
7344 : * This function is the same as the C function
7345 : * OGR_F_GetNativeMediaType().
7346 : *
7347 : * @return a string with the native media type, or NULL if there is none.
7348 : *
7349 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7350 : */
7351 :
7352 : /************************************************************************/
7353 : /* OGR_F_GetNativeMediaType() */
7354 : /************************************************************************/
7355 :
7356 : /**
7357 : * \brief Returns the native media type for the feature.
7358 : *
7359 : * The native media type is the identifier for the format of the native data.
7360 : * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
7361 : * e.g. "application/vnd.geo+json" for JSon.
7362 : *
7363 : * This function is the same as the C function
7364 : * OGR_F_GetNativeMediaType().
7365 : *
7366 : * @param hFeat handle to the feature.
7367 : * @return a string with the native media type, or NULL if there is none.
7368 : *
7369 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7370 : */
7371 :
7372 9 : const char *OGR_F_GetNativeMediaType(OGRFeatureH hFeat)
7373 : {
7374 9 : VALIDATE_POINTER1(hFeat, "OGR_F_GetNativeMediaType", nullptr);
7375 :
7376 9 : return OGRFeature::FromHandle(hFeat)->GetNativeMediaType();
7377 : }
7378 :
7379 : /************************************************************************/
7380 : /* 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 : * GetNativeMediaType().
7390 : *
7391 : * This function is the same as the C function
7392 : * OGR_F_SetNativeData().
7393 : *
7394 : * @param pszNativeData a string with the native data, or NULL if there is none.
7395 : *
7396 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7397 : */
7398 :
7399 15260 : void OGRFeature::SetNativeData(const char *pszNativeData)
7400 : {
7401 15260 : CPLFree(m_pszNativeData);
7402 15260 : m_pszNativeData =
7403 15260 : pszNativeData ? VSI_STRDUP_VERBOSE(pszNativeData) : nullptr;
7404 15260 : }
7405 :
7406 : /************************************************************************/
7407 : /* OGR_F_SetNativeData() */
7408 : /************************************************************************/
7409 :
7410 : /**
7411 : * \brief Sets the native data for the feature.
7412 : *
7413 : * The native data is the representation in a "natural" form that comes from
7414 : * the driver that created this feature, or that is aimed at an output driver.
7415 : * The native data may be in different format, which is indicated by
7416 : * OGR_F_GetNativeMediaType().
7417 : *
7418 : * This function is the same as the C++ method
7419 : * OGRFeature::SetNativeData().
7420 : *
7421 : * @param hFeat handle to the feature.
7422 : * @param pszNativeData a string with the native data, or NULL if there is none.
7423 : *
7424 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7425 : */
7426 :
7427 4 : void OGR_F_SetNativeData(OGRFeatureH hFeat, const char *pszNativeData)
7428 : {
7429 4 : VALIDATE_POINTER0(hFeat, "OGR_F_SetNativeData");
7430 :
7431 4 : OGRFeature::FromHandle(hFeat)->SetNativeData(pszNativeData);
7432 : }
7433 :
7434 : /************************************************************************/
7435 : /* SetNativeMediaType() */
7436 : /************************************************************************/
7437 :
7438 : /**
7439 : * \brief Sets the native media type for the feature.
7440 : *
7441 : * The native media type is the identifier for the format of the native data.
7442 : * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
7443 : * e.g. "application/vnd.geo+json" for JSon.
7444 : *
7445 : * This function is the same as the C function
7446 : * OGR_F_SetNativeMediaType().
7447 : *
7448 : * @param pszNativeMediaType a string with the native media type, or NULL if
7449 : * there is none.
7450 : *
7451 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7452 : */
7453 :
7454 15260 : void OGRFeature::SetNativeMediaType(const char *pszNativeMediaType)
7455 : {
7456 15260 : CPLFree(m_pszNativeMediaType);
7457 15260 : m_pszNativeMediaType =
7458 15260 : pszNativeMediaType ? VSI_STRDUP_VERBOSE(pszNativeMediaType) : nullptr;
7459 15260 : }
7460 :
7461 : /************************************************************************/
7462 : /* OGR_F_SetNativeMediaType() */
7463 : /************************************************************************/
7464 :
7465 : /**
7466 : * \brief Sets the native media type for the feature.
7467 : *
7468 : * The native media type is the identifier for the format of the native data.
7469 : * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
7470 : * e.g. "application/vnd.geo+json" for JSon.
7471 : *
7472 : * This function is the same as the C++ method
7473 : * OGRFeature::SetNativeMediaType().
7474 : *
7475 : * @param hFeat handle to the feature.
7476 : * @param pszNativeMediaType a string with the native media type, or NULL if
7477 : * there is none.
7478 : *
7479 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7480 : */
7481 :
7482 4 : void OGR_F_SetNativeMediaType(OGRFeatureH hFeat, const char *pszNativeMediaType)
7483 : {
7484 4 : VALIDATE_POINTER0(hFeat, "OGR_F_SetNativeMediaType");
7485 :
7486 4 : OGRFeature::FromHandle(hFeat)->SetNativeMediaType(pszNativeMediaType);
7487 : }
7488 :
7489 : /************************************************************************/
7490 : /* OGR_RawField_IsUnset() */
7491 : /************************************************************************/
7492 :
7493 : /**
7494 : * \brief Returns whether a raw field is unset.
7495 : *
7496 : * Note: this function is rather low-level and should be rarely used in client
7497 : * code. Use instead OGR_F_IsFieldSet().
7498 : *
7499 : * @param puField pointer to raw field.
7500 : */
7501 :
7502 3741810 : int OGR_RawField_IsUnset(const OGRField *puField)
7503 : {
7504 5176920 : return puField->Set.nMarker1 == OGRUnsetMarker &&
7505 5176920 : puField->Set.nMarker2 == OGRUnsetMarker &&
7506 5176920 : puField->Set.nMarker3 == OGRUnsetMarker;
7507 : }
7508 :
7509 : /************************************************************************/
7510 : /* OGR_RawField_IsNull() */
7511 : /************************************************************************/
7512 :
7513 : /**
7514 : * \brief Returns whether a raw field is null.
7515 : *
7516 : * Note: this function is rather low-level and should be rarely used in client
7517 : * code. Use instead OGR_F_IsFieldNull().
7518 : *
7519 : * @param puField pointer to raw field.
7520 : */
7521 :
7522 2293760 : int OGR_RawField_IsNull(const OGRField *puField)
7523 : {
7524 2298480 : return puField->Set.nMarker1 == OGRNullMarker &&
7525 2298480 : puField->Set.nMarker2 == OGRNullMarker &&
7526 2298480 : puField->Set.nMarker3 == OGRNullMarker;
7527 : }
7528 :
7529 : /************************************************************************/
7530 : /* OGR_RawField_SetUnset() */
7531 : /************************************************************************/
7532 :
7533 : /**
7534 : * \brief Mark a raw field as unset.
7535 : *
7536 : * This should be called on a un-initialized field. In particular this will not
7537 : * free any memory dynamically allocated.
7538 : *
7539 : * Note: this function is rather low-level and should be rarely used in client
7540 : * code. Use instead OGR_F_UnsetField().
7541 : *
7542 : * @param puField pointer to raw field.
7543 : */
7544 :
7545 116096 : void OGR_RawField_SetUnset(OGRField *puField)
7546 : {
7547 116096 : puField->Set.nMarker1 = OGRUnsetMarker;
7548 116096 : puField->Set.nMarker2 = OGRUnsetMarker;
7549 116096 : puField->Set.nMarker3 = OGRUnsetMarker;
7550 116096 : }
7551 :
7552 : /************************************************************************/
7553 : /* OGR_RawField_SetNull() */
7554 : /************************************************************************/
7555 :
7556 : /**
7557 : * \brief Mark a raw field as null.
7558 : *
7559 : * This should be called on a un-initialized field. In particular this will not
7560 : * free any memory dynamically allocated.
7561 : *
7562 : * Note: this function is rather low-level and should be rarely used in client
7563 : * code. Use instead OGR_F_SetFieldNull().
7564 : *
7565 : * @param puField pointer to raw field.
7566 : */
7567 :
7568 57171 : void OGR_RawField_SetNull(OGRField *puField)
7569 : {
7570 57171 : puField->Set.nMarker1 = OGRNullMarker;
7571 57171 : puField->Set.nMarker2 = OGRNullMarker;
7572 57171 : puField->Set.nMarker3 = OGRNullMarker;
7573 57171 : }
7574 :
7575 : /************************************************************************/
7576 : /* OGRFeatureUniquePtrDeleter */
7577 : /************************************************************************/
7578 :
7579 : //! @cond Doxygen_Suppress
7580 167161 : void OGRFeatureUniquePtrDeleter::operator()(OGRFeature *poFeature) const
7581 : {
7582 167161 : delete poFeature;
7583 167161 : }
7584 :
7585 : //! @endcond
7586 :
7587 : namespace
7588 : {
7589 : // Implementation borrowed to OpenFileGDB
7590 :
7591 : /************************************************************************/
7592 : /* WriteUInt8() */
7593 : /************************************************************************/
7594 :
7595 11025 : inline void WriteUInt8(std::vector<GByte> &abyBuffer, uint8_t nVal)
7596 : {
7597 11025 : abyBuffer.push_back(nVal);
7598 11025 : }
7599 :
7600 : /************************************************************************/
7601 : /* WriteVarUInt() */
7602 : /************************************************************************/
7603 :
7604 5789 : inline void WriteVarUInt(std::vector<GByte> &abyBuffer, uint64_t nVal)
7605 : {
7606 : while (true)
7607 : {
7608 5789 : if (nVal >= 0x80)
7609 : {
7610 16 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nVal & 0x7F)));
7611 16 : nVal >>= 7;
7612 : }
7613 : else
7614 : {
7615 5773 : WriteUInt8(abyBuffer, static_cast<uint8_t>(nVal));
7616 5773 : break;
7617 : }
7618 : }
7619 5773 : }
7620 :
7621 : /************************************************************************/
7622 : /* WriteVarInt() */
7623 : /************************************************************************/
7624 :
7625 5226 : inline void WriteVarInt(std::vector<GByte> &abyBuffer, int64_t nVal)
7626 : {
7627 : uint64_t nUVal;
7628 5226 : if (nVal < 0)
7629 : {
7630 7 : if (nVal == std::numeric_limits<int64_t>::min())
7631 0 : nUVal = static_cast<uint64_t>(1) << 63;
7632 : else
7633 7 : nUVal = -nVal;
7634 7 : if (nUVal >= 0x40)
7635 : {
7636 5 : WriteUInt8(abyBuffer,
7637 5 : static_cast<uint8_t>(0x80 | 0x40 | (nUVal & 0x3F)));
7638 5 : nUVal >>= 6;
7639 : }
7640 : else
7641 : {
7642 2 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x40 | (nUVal & 0x3F)));
7643 2 : return;
7644 : }
7645 : }
7646 : else
7647 : {
7648 5219 : nUVal = nVal;
7649 5219 : if (nUVal >= 0x40)
7650 : {
7651 4170 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nUVal & 0x3F)));
7652 4170 : nUVal >>= 6;
7653 : }
7654 : else
7655 : {
7656 1049 : WriteUInt8(abyBuffer, static_cast<uint8_t>((nUVal & 0x3F)));
7657 1049 : return;
7658 : }
7659 : }
7660 :
7661 4175 : WriteVarUInt(abyBuffer, nUVal);
7662 : }
7663 :
7664 : /************************************************************************/
7665 : /* WriteFloat32() */
7666 : /************************************************************************/
7667 :
7668 2 : inline void WriteFloat32(std::vector<GByte> &abyBuffer, float fVal)
7669 : {
7670 2 : CPL_LSBPTR32(&fVal);
7671 2 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&fVal);
7672 2 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(fVal));
7673 2 : }
7674 :
7675 : /************************************************************************/
7676 : /* WriteFloat64() */
7677 : /************************************************************************/
7678 :
7679 3 : inline void WriteFloat64(std::vector<GByte> &abyBuffer, double dfVal)
7680 : {
7681 3 : CPL_LSBPTR64(&dfVal);
7682 3 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&dfVal);
7683 3 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(dfVal));
7684 3 : }
7685 :
7686 : } // namespace
7687 :
7688 : /************************************************************************/
7689 : /* OGRFeature::SerializeToBinary() */
7690 : /************************************************************************/
7691 :
7692 : /** Serialize the feature to a binary encoding.
7693 : *
7694 : * This saves the feature ID, attribute fields content and geometry fields
7695 : * content.
7696 : *
7697 : * This method is aimed at being paired with DeserializeFromBinary().
7698 : *
7699 : * The format of that encoding may vary across GDAL versions.
7700 : *
7701 : * Note that abyBuffer is cleared at the beginning of this function.
7702 : *
7703 : * @since 3.9
7704 : */
7705 2609 : bool OGRFeature::SerializeToBinary(std::vector<GByte> &abyBuffer) const
7706 : {
7707 2609 : const int nFieldCount = poDefn->GetFieldCount();
7708 2609 : const int nGeomFieldCount = poDefn->GetGeomFieldCount();
7709 : try
7710 : {
7711 2609 : abyBuffer.clear();
7712 : // Set field flags
7713 : // For attribute fields, we have 2 bits
7714 : // - first one set if the field is unset
7715 : // - second one set if the field is null
7716 : // For geometry fields, we have one bit set to indicate if the geometry
7717 : // is non-null.
7718 2609 : const size_t nPresenceFlagsSize =
7719 2609 : ((2 * nFieldCount + nGeomFieldCount) + 7) / 8;
7720 2609 : abyBuffer.resize(nPresenceFlagsSize);
7721 :
7722 2609 : WriteVarInt(abyBuffer, GetFID());
7723 :
7724 1036 : const auto SetFlagBit = [&abyBuffer](int iBit)
7725 1036 : { abyBuffer[iBit / 8] |= (1 << (iBit % 8)); };
7726 :
7727 5249 : for (int i = 0; i < nFieldCount; ++i)
7728 : {
7729 2640 : const OGRField &uField = pauFields[i];
7730 2640 : if (OGR_RawField_IsUnset(&uField))
7731 : {
7732 23 : const int iBit = 2 * i;
7733 23 : SetFlagBit(iBit);
7734 23 : continue;
7735 : }
7736 2617 : if (OGR_RawField_IsNull(&uField))
7737 : {
7738 1 : const int iBit = 2 * i + 1;
7739 1 : SetFlagBit(iBit);
7740 1 : continue;
7741 : }
7742 2616 : const auto poFDefn = poDefn->GetFieldDefn(i);
7743 2616 : switch (poFDefn->GetType())
7744 : {
7745 2605 : case OFTInteger:
7746 : {
7747 2605 : WriteVarInt(abyBuffer, uField.Integer);
7748 2605 : break;
7749 : }
7750 1 : case OFTInteger64:
7751 : {
7752 1 : WriteVarInt(abyBuffer, uField.Integer64);
7753 1 : break;
7754 : }
7755 1 : case OFTReal:
7756 : {
7757 1 : WriteFloat64(abyBuffer, uField.Real);
7758 1 : break;
7759 : }
7760 1 : case OFTString:
7761 : {
7762 1 : const size_t nStrSize = strlen(uField.String);
7763 1 : WriteVarUInt(abyBuffer, nStrSize);
7764 1 : const GByte *pabyStr =
7765 : reinterpret_cast<const GByte *>(uField.String);
7766 0 : abyBuffer.insert(abyBuffer.end(), pabyStr,
7767 1 : pabyStr + nStrSize);
7768 1 : break;
7769 : }
7770 1 : case OFTIntegerList:
7771 : {
7772 1 : WriteVarInt(abyBuffer, uField.IntegerList.nCount);
7773 3 : for (int j = 0; j < uField.IntegerList.nCount; ++j)
7774 2 : WriteVarInt(abyBuffer, uField.IntegerList.paList[j]);
7775 1 : break;
7776 : }
7777 1 : case OFTInteger64List:
7778 : {
7779 1 : WriteVarInt(abyBuffer, uField.Integer64List.nCount);
7780 3 : for (int j = 0; j < uField.Integer64List.nCount; ++j)
7781 2 : WriteVarInt(abyBuffer, uField.Integer64List.paList[j]);
7782 1 : break;
7783 : }
7784 1 : case OFTRealList:
7785 : {
7786 1 : WriteVarInt(abyBuffer, uField.RealList.nCount);
7787 3 : for (int j = 0; j < uField.RealList.nCount; ++j)
7788 2 : WriteFloat64(abyBuffer, uField.RealList.paList[j]);
7789 1 : break;
7790 : }
7791 1 : case OFTStringList:
7792 : {
7793 1 : WriteVarInt(abyBuffer, uField.StringList.nCount);
7794 3 : for (int j = 0; j < uField.StringList.nCount; ++j)
7795 : {
7796 2 : const char *pszStr = uField.StringList.paList[j];
7797 2 : const size_t nStrSize = strlen(pszStr);
7798 2 : WriteVarUInt(abyBuffer, nStrSize);
7799 2 : const GByte *pabyStr =
7800 : reinterpret_cast<const GByte *>(pszStr);
7801 0 : abyBuffer.insert(abyBuffer.end(), pabyStr,
7802 2 : pabyStr + nStrSize);
7803 : }
7804 1 : break;
7805 : }
7806 1 : case OFTBinary:
7807 : {
7808 1 : WriteVarInt(abyBuffer, uField.Binary.nCount);
7809 0 : abyBuffer.insert(abyBuffer.end(), uField.Binary.paData,
7810 1 : uField.Binary.paData +
7811 1 : uField.Binary.nCount);
7812 1 : break;
7813 : }
7814 0 : case OFTWideString:
7815 : case OFTWideStringList:
7816 0 : break;
7817 1 : case OFTDate:
7818 : {
7819 1 : WriteVarInt(abyBuffer, uField.Date.Year);
7820 1 : WriteUInt8(abyBuffer, uField.Date.Month);
7821 1 : WriteUInt8(abyBuffer, uField.Date.Day);
7822 1 : break;
7823 : }
7824 1 : case OFTTime:
7825 : {
7826 1 : WriteUInt8(abyBuffer, uField.Date.Hour);
7827 1 : WriteUInt8(abyBuffer, uField.Date.Minute);
7828 1 : WriteFloat32(abyBuffer, uField.Date.Second);
7829 1 : WriteUInt8(abyBuffer, uField.Date.TZFlag);
7830 1 : break;
7831 : }
7832 1 : case OFTDateTime:
7833 : {
7834 1 : WriteVarInt(abyBuffer, uField.Date.Year);
7835 1 : WriteUInt8(abyBuffer, uField.Date.Month);
7836 1 : WriteUInt8(abyBuffer, uField.Date.Day);
7837 1 : WriteUInt8(abyBuffer, uField.Date.Hour);
7838 1 : WriteUInt8(abyBuffer, uField.Date.Minute);
7839 1 : WriteFloat32(abyBuffer, uField.Date.Second);
7840 1 : WriteUInt8(abyBuffer, uField.Date.TZFlag);
7841 1 : break;
7842 : }
7843 : }
7844 : }
7845 5216 : for (int i = 0; i < nGeomFieldCount; ++i)
7846 : {
7847 2607 : if (!papoGeometries[i])
7848 : {
7849 1012 : const int iBit = 2 * nFieldCount + i;
7850 1012 : SetFlagBit(iBit);
7851 1012 : continue;
7852 : }
7853 1595 : const size_t nSize = papoGeometries[i]->WkbSize();
7854 1595 : WriteVarUInt(abyBuffer, nSize);
7855 1595 : const size_t nBufSizeBefore = abyBuffer.size();
7856 1595 : abyBuffer.resize(nBufSizeBefore + nSize);
7857 1595 : papoGeometries[i]->exportToWkb(
7858 1595 : wkbNDR, abyBuffer.data() + nBufSizeBefore, wkbVariantIso);
7859 : }
7860 2609 : return true;
7861 : }
7862 0 : catch (const std::bad_alloc &)
7863 : {
7864 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
7865 0 : return false;
7866 : }
7867 : }
7868 :
7869 : namespace
7870 : {
7871 : // Implementation borrowed to OpenFileGDB
7872 :
7873 : /************************************************************************/
7874 : /* ReadVarUInt() */
7875 : /************************************************************************/
7876 :
7877 : template <class OutType>
7878 2197 : static bool ReadVarUInt(const GByte *&pabyIter, const GByte *pabyEnd,
7879 : OutType &nOutVal)
7880 : {
7881 2197 : if (pabyIter >= pabyEnd)
7882 3 : return false;
7883 2194 : OutType b = *pabyIter;
7884 2194 : if ((b & 0x80) == 0)
7885 : {
7886 2189 : pabyIter++;
7887 2189 : nOutVal = b;
7888 2189 : return true;
7889 : }
7890 5 : const GByte *pabyLocalIter = pabyIter + 1;
7891 5 : int nShift = 7;
7892 5 : OutType nVal = (b & 0x7F);
7893 : while (true)
7894 : {
7895 5 : if (pabyLocalIter >= pabyEnd)
7896 0 : return false;
7897 5 : b = *pabyLocalIter;
7898 5 : pabyLocalIter++;
7899 5 : nVal |= (b & 0x7F) << nShift;
7900 5 : if ((b & 0x80) == 0)
7901 : {
7902 5 : pabyIter = pabyLocalIter;
7903 5 : nOutVal = nVal;
7904 5 : return true;
7905 : }
7906 0 : nShift += 7;
7907 : // To avoid undefined behavior later when doing << nShift
7908 0 : if (nShift >= static_cast<int>(sizeof(OutType)) * 8)
7909 : {
7910 0 : return false;
7911 : }
7912 : }
7913 : }
7914 :
7915 : /************************************************************************/
7916 : /* ReadVarInt() */
7917 : /************************************************************************/
7918 :
7919 : template <class OutType>
7920 : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW static bool
7921 7811 : ReadVarInt(const GByte *&pabyIter, const GByte *pabyEnd, OutType &nOutVal)
7922 : {
7923 : GUInt32 b;
7924 :
7925 7811 : if (pabyIter >= pabyEnd)
7926 15 : return false;
7927 7796 : b = *pabyIter;
7928 7796 : GUIntBig nVal = (b & 0x3F);
7929 7796 : bool bNegative = (b & 0x40) != 0;
7930 7796 : if ((b & 0x80) == 0)
7931 : {
7932 2545 : pabyIter++;
7933 2545 : if (bNegative)
7934 4 : nOutVal = -static_cast<OutType>(nVal);
7935 : else
7936 2541 : nOutVal = static_cast<OutType>(nVal);
7937 2545 : return true;
7938 : }
7939 :
7940 5251 : const GByte *pabyLocalIter = pabyIter + 1;
7941 5251 : int nShift = 6;
7942 2179 : while (true)
7943 : {
7944 7430 : if (pabyLocalIter >= pabyEnd)
7945 23 : return false;
7946 7407 : GUIntBig b64 = *pabyLocalIter;
7947 7407 : pabyLocalIter++;
7948 7407 : nVal |= (b64 & 0x7F) << nShift;
7949 7407 : if ((b64 & 0x80) == 0)
7950 : {
7951 5228 : pabyIter = pabyLocalIter;
7952 5228 : if (bNegative)
7953 813 : nOutVal = -static_cast<OutType>(nVal);
7954 : else
7955 4415 : nOutVal = static_cast<OutType>(nVal);
7956 5228 : return true;
7957 : }
7958 2179 : nShift += 7;
7959 : // To avoid undefined behavior later when doing << nShift
7960 2179 : if (nShift >= static_cast<int>(sizeof(GIntBig)) * 8)
7961 : {
7962 0 : return false;
7963 : }
7964 : }
7965 : }
7966 :
7967 : /************************************************************************/
7968 : /* ReadUInt8() */
7969 : /************************************************************************/
7970 :
7971 1207 : inline bool ReadUInt8(const GByte *&pabyIter, const GByte *pabyEnd, GByte &nVal)
7972 : {
7973 1207 : if (pabyIter + sizeof(nVal) > pabyEnd)
7974 10 : return false;
7975 1197 : nVal = *pabyIter;
7976 1197 : pabyIter += sizeof(nVal);
7977 1197 : return true;
7978 : }
7979 :
7980 : /************************************************************************/
7981 : /* ReadFloat32() */
7982 : /************************************************************************/
7983 :
7984 239 : inline bool ReadFloat32(const GByte *&pabyIter, const GByte *pabyEnd,
7985 : float &fVal)
7986 : {
7987 239 : if (pabyIter + sizeof(fVal) > pabyEnd)
7988 8 : return false;
7989 : // cppcheck-suppress bufferAccessOutOfBounds
7990 231 : memcpy(&fVal, pabyIter, sizeof(fVal));
7991 231 : CPL_LSBPTR32(&fVal);
7992 231 : pabyIter += sizeof(fVal);
7993 231 : return true;
7994 : }
7995 :
7996 : /************************************************************************/
7997 : /* ReadFloat64() */
7998 : /************************************************************************/
7999 :
8000 541 : inline bool ReadFloat64(const GByte *&pabyIter, const GByte *pabyEnd,
8001 : double &dfVal)
8002 : {
8003 541 : if (pabyIter + sizeof(dfVal) > pabyEnd)
8004 22 : return false;
8005 519 : memcpy(&dfVal, pabyIter, sizeof(dfVal));
8006 519 : CPL_LSBPTR64(&dfVal);
8007 519 : pabyIter += sizeof(dfVal);
8008 519 : return true;
8009 : }
8010 :
8011 : } // namespace
8012 :
8013 : /************************************************************************/
8014 : /* OGRFeature::DeserializeFromBinary() */
8015 : /************************************************************************/
8016 :
8017 : /** Instantiate a feature from a binary encoding produces by SerializeToBinary()
8018 : *
8019 : * This sets the feature ID, attribute fields content and geometry fields
8020 : * content.
8021 : *
8022 : * DeserializeFromBinary() should be called on a feature whose feature definition
8023 : * is exactly the same as the one on which SerializeToBinary() was called.
8024 : * (but there is no security issue if not doing that, or if feeding a "random"
8025 : * buffer to that method).
8026 : *
8027 : * The format of that encoding may vary across GDAL versions.
8028 : *
8029 : * @since 3.9
8030 : */
8031 2861 : bool OGRFeature::DeserializeFromBinary(const GByte *pabyBuffer, size_t nSize)
8032 : {
8033 2861 : Reset();
8034 :
8035 2861 : const GByte *const pabyFlags = pabyBuffer;
8036 2861 : const GByte *const pabyEnd = pabyBuffer + nSize;
8037 2861 : const int nFieldCount = poDefn->GetFieldCount();
8038 2861 : const int nGeomFieldCount = poDefn->GetGeomFieldCount();
8039 2861 : const size_t nPresenceFlagsSize =
8040 2861 : ((2 * nFieldCount + nGeomFieldCount) + 7) / 8;
8041 2861 : if (nSize < nPresenceFlagsSize)
8042 12 : return false;
8043 2849 : pabyBuffer += nPresenceFlagsSize;
8044 :
8045 2849 : if (!ReadVarInt(pabyBuffer, pabyEnd, nFID))
8046 11 : return false;
8047 :
8048 12305 : const auto IsFlagBitSet = [pabyFlags](int iBit) -> bool
8049 12305 : { return (pabyFlags[iBit / 8] & (1 << (iBit % 8))) != 0; };
8050 :
8051 7530 : for (int i = 0; i < nFieldCount; ++i)
8052 : {
8053 4812 : OGRField &uField = pauFields[i];
8054 : {
8055 4812 : const int iBit = 2 * i;
8056 4812 : if (IsFlagBitSet(iBit))
8057 : {
8058 : // OGR_RawField_SetUnset(&uField);
8059 35 : continue;
8060 : }
8061 : }
8062 : {
8063 4777 : const int iBit = 2 * i + 1;
8064 4777 : if (IsFlagBitSet(iBit))
8065 : {
8066 1 : OGR_RawField_SetNull(&uField);
8067 1 : continue;
8068 : }
8069 : }
8070 4776 : const auto poFDefn = poDefn->GetFieldDefn(i);
8071 4776 : switch (poFDefn->GetType())
8072 : {
8073 2833 : case OFTInteger:
8074 : {
8075 2833 : uField.Set.nMarker2 = 0;
8076 2833 : uField.Set.nMarker3 = 0;
8077 2833 : if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Integer))
8078 2 : return false;
8079 2831 : break;
8080 : }
8081 227 : case OFTInteger64:
8082 : {
8083 227 : uField.Set.nMarker2 = 0;
8084 227 : uField.Set.nMarker3 = 0;
8085 227 : if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Integer64))
8086 7 : return false;
8087 220 : break;
8088 : }
8089 220 : case OFTReal:
8090 : {
8091 220 : uField.Set.nMarker2 = 0;
8092 220 : uField.Set.nMarker3 = 0;
8093 220 : if (!ReadFloat64(pabyBuffer, pabyEnd, uField.Real))
8094 8 : return false;
8095 212 : break;
8096 : }
8097 212 : case OFTString:
8098 : {
8099 212 : size_t nStrSize = 0;
8100 423 : if (!ReadVarUInt(pabyBuffer, pabyEnd, nStrSize) ||
8101 211 : nStrSize > std::numeric_limits<size_t>::max() - 1)
8102 : {
8103 9 : return false;
8104 : }
8105 211 : if (nStrSize > static_cast<size_t>(pabyEnd - pabyBuffer))
8106 8 : return false;
8107 : auto ptr =
8108 203 : static_cast<char *>(VSI_MALLOC_VERBOSE(nStrSize + 1));
8109 203 : if (!ptr)
8110 0 : return false;
8111 203 : uField.Set.nMarker2 = 0;
8112 203 : uField.Set.nMarker3 = 0;
8113 203 : uField.String = ptr;
8114 203 : memcpy(uField.String, pabyBuffer, nStrSize);
8115 203 : uField.String[nStrSize] = 0;
8116 203 : pabyBuffer += nStrSize;
8117 203 : break;
8118 : }
8119 196 : case OFTIntegerList:
8120 : {
8121 196 : int nCount = 0;
8122 388 : if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
8123 192 : nCount > pabyEnd - pabyBuffer)
8124 : {
8125 11 : return false;
8126 : }
8127 : auto ptr = static_cast<int *>(
8128 190 : VSI_MALLOC2_VERBOSE(nCount, sizeof(int)));
8129 190 : if (!ptr)
8130 3 : return false;
8131 187 : uField.Set.nMarker2 = 0;
8132 187 : uField.Set.nMarker3 = 0;
8133 187 : uField.IntegerList.paList = ptr;
8134 187 : uField.IntegerList.nCount = nCount;
8135 559 : for (int j = 0; j < nCount; ++j)
8136 : {
8137 374 : if (!ReadVarInt(pabyBuffer, pabyEnd,
8138 374 : uField.IntegerList.paList[j]))
8139 2 : return false;
8140 : }
8141 185 : break;
8142 : }
8143 185 : case OFTInteger64List:
8144 : {
8145 185 : int nCount = 0;
8146 368 : if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
8147 183 : nCount > pabyEnd - pabyBuffer)
8148 : {
8149 11 : return false;
8150 : }
8151 : auto ptr = static_cast<GIntBig *>(
8152 180 : VSI_MALLOC2_VERBOSE(nCount, sizeof(GIntBig)));
8153 180 : if (!ptr)
8154 0 : return false;
8155 180 : uField.Set.nMarker2 = 0;
8156 180 : uField.Set.nMarker3 = 0;
8157 180 : uField.Integer64List.paList = ptr;
8158 180 : uField.Integer64List.nCount = nCount;
8159 545 : for (int j = 0; j < nCount; ++j)
8160 : {
8161 371 : if (!ReadVarInt(pabyBuffer, pabyEnd,
8162 371 : uField.Integer64List.paList[j]))
8163 6 : return false;
8164 : }
8165 174 : break;
8166 : }
8167 174 : case OFTRealList:
8168 : {
8169 174 : int nCount = 0;
8170 343 : if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
8171 169 : nCount > pabyEnd - pabyBuffer)
8172 : {
8173 26 : return false;
8174 : }
8175 : auto ptr = static_cast<double *>(
8176 165 : VSI_MALLOC2_VERBOSE(nCount, sizeof(double)));
8177 165 : if (!ptr)
8178 3 : return false;
8179 162 : uField.Set.nMarker2 = 0;
8180 162 : uField.Set.nMarker3 = 0;
8181 162 : uField.RealList.paList = ptr;
8182 162 : uField.RealList.nCount = nCount;
8183 469 : for (int j = 0; j < nCount; ++j)
8184 : {
8185 321 : if (!ReadFloat64(pabyBuffer, pabyEnd,
8186 321 : uField.RealList.paList[j]))
8187 14 : return false;
8188 : }
8189 148 : break;
8190 : }
8191 148 : case OFTStringList:
8192 : {
8193 148 : int nCount = 0;
8194 295 : if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
8195 441 : nCount > std::numeric_limits<int>::max() - 1 ||
8196 146 : nCount > pabyEnd - pabyBuffer)
8197 : {
8198 17 : return false;
8199 : }
8200 : auto ptr = static_cast<char **>(
8201 143 : VSI_CALLOC_VERBOSE(nCount + 1, sizeof(char *)));
8202 143 : if (!ptr)
8203 0 : return false;
8204 143 : uField.Set.nMarker2 = 0;
8205 143 : uField.Set.nMarker3 = 0;
8206 143 : uField.StringList.paList = ptr;
8207 143 : uField.StringList.nCount = nCount;
8208 413 : for (int j = 0; j < nCount; ++j)
8209 : {
8210 282 : size_t nStrSize = 0;
8211 563 : if (!ReadVarUInt(pabyBuffer, pabyEnd, nStrSize) ||
8212 281 : nStrSize > std::numeric_limits<size_t>::max() - 1)
8213 : {
8214 12 : return false;
8215 : }
8216 281 : if (nStrSize > static_cast<size_t>(pabyEnd - pabyBuffer))
8217 11 : return false;
8218 540 : uField.StringList.paList[j] =
8219 270 : static_cast<char *>(VSI_MALLOC_VERBOSE(nStrSize + 1));
8220 270 : if (!uField.StringList.paList[j])
8221 0 : return false;
8222 270 : memcpy(uField.StringList.paList[j], pabyBuffer, nStrSize);
8223 270 : uField.StringList.paList[j][nStrSize] = 0;
8224 270 : pabyBuffer += nStrSize;
8225 : }
8226 131 : break;
8227 : }
8228 203 : case OFTBinary:
8229 : {
8230 203 : int nBinSize = 0;
8231 203 : if (!ReadVarInt(pabyBuffer, pabyEnd, nBinSize) || nBinSize < 0)
8232 : {
8233 7 : return false;
8234 : }
8235 199 : if (nBinSize > pabyEnd - pabyBuffer)
8236 3 : return false;
8237 196 : auto ptr = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nBinSize));
8238 196 : if (!ptr)
8239 0 : return false;
8240 196 : uField.Set.nMarker2 = 0;
8241 196 : uField.Set.nMarker3 = 0;
8242 196 : uField.Binary.paData = ptr;
8243 196 : uField.Binary.nCount = nBinSize;
8244 196 : memcpy(uField.Binary.paData, pabyBuffer, nBinSize);
8245 196 : pabyBuffer += nBinSize;
8246 196 : break;
8247 : }
8248 0 : case OFTWideString:
8249 : case OFTWideStringList:
8250 0 : break;
8251 131 : case OFTDate:
8252 : {
8253 131 : memset(&uField, 0, sizeof(uField));
8254 131 : if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Date.Year) ||
8255 259 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Month) ||
8256 128 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Day))
8257 : {
8258 4 : return false;
8259 : }
8260 127 : break;
8261 : }
8262 127 : case OFTTime:
8263 : {
8264 127 : memset(&uField, 0, sizeof(uField));
8265 127 : if (!ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Hour) ||
8266 126 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Minute) ||
8267 374 : !ReadFloat32(pabyBuffer, pabyEnd, uField.Date.Second) ||
8268 121 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.TZFlag))
8269 : {
8270 7 : return false;
8271 : }
8272 120 : break;
8273 : }
8274 120 : case OFTDateTime:
8275 : {
8276 120 : memset(&uField, 0, sizeof(uField));
8277 120 : if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Date.Year) ||
8278 118 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Month) ||
8279 117 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Day) ||
8280 116 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Hour) ||
8281 115 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Minute) ||
8282 348 : !ReadFloat32(pabyBuffer, pabyEnd, uField.Date.Second) ||
8283 110 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.TZFlag))
8284 : {
8285 11 : return false;
8286 : }
8287 109 : break;
8288 : }
8289 : }
8290 : }
8291 5402 : for (int i = 0; i < nGeomFieldCount; ++i)
8292 : {
8293 2716 : const int iBit = 2 * nFieldCount + i;
8294 2716 : if (IsFlagBitSet(iBit))
8295 : {
8296 1013 : continue;
8297 : }
8298 1703 : size_t nWkbSize = 0;
8299 1703 : if (!ReadVarUInt(pabyBuffer, pabyEnd, nWkbSize))
8300 : {
8301 32 : return false;
8302 : }
8303 1702 : if (nWkbSize > static_cast<size_t>(pabyEnd - pabyBuffer))
8304 : {
8305 23 : return false;
8306 : }
8307 1679 : OGRGeometry *poGeom = nullptr;
8308 1679 : if (OGRGeometryFactory::createFromWkb(
8309 1679 : pabyBuffer, poDefn->GetGeomFieldDefn(i)->GetSpatialRef(),
8310 3350 : &poGeom, nWkbSize, wkbVariantIso) != OGRERR_NONE ||
8311 1671 : !poGeom)
8312 : {
8313 8 : delete poGeom;
8314 8 : return false;
8315 : }
8316 1671 : pabyBuffer += nWkbSize;
8317 1671 : papoGeometries[i] = poGeom;
8318 : }
8319 2686 : return true;
8320 : }
8321 :
8322 : /************************************************************************/
8323 : /* OGRFeature::ConstFieldIterator */
8324 : /************************************************************************/
8325 :
8326 : struct OGRFeature::FieldValue::Private
8327 : {
8328 : CPL_DISALLOW_COPY_ASSIGN(Private)
8329 :
8330 : OGRFeature *m_poSelf = nullptr;
8331 : int m_nPos = 0;
8332 : mutable std::vector<int> m_anList{};
8333 : mutable std::vector<GIntBig> m_anList64{};
8334 : mutable std::vector<double> m_adfList{};
8335 : mutable std::vector<std::string> m_aosList{};
8336 :
8337 4 : Private(const OGRFeature *poSelf, int iFieldIndex)
8338 4 : : m_poSelf(const_cast<OGRFeature *>(poSelf)), m_nPos(iFieldIndex)
8339 : {
8340 4 : }
8341 :
8342 47 : Private(OGRFeature *poSelf, int iFieldIndex)
8343 47 : : m_poSelf(poSelf), m_nPos(iFieldIndex)
8344 : {
8345 47 : }
8346 : };
8347 :
8348 : struct OGRFeature::ConstFieldIterator::Private
8349 : {
8350 : CPL_DISALLOW_COPY_ASSIGN(Private)
8351 :
8352 : OGRFeature::FieldValue m_oValue;
8353 : int m_nPos = 0;
8354 :
8355 4 : Private(const OGRFeature *poSelf, int iFieldIndex)
8356 4 : : m_oValue(poSelf, iFieldIndex)
8357 : {
8358 4 : }
8359 : };
8360 :
8361 : //! @cond Doxygen_Suppress
8362 4 : OGRFeature::ConstFieldIterator::ConstFieldIterator(const OGRFeature *poSelf,
8363 4 : int nPos)
8364 4 : : m_poPrivate(new Private(poSelf, nPos))
8365 : {
8366 4 : m_poPrivate->m_nPos = nPos;
8367 4 : }
8368 :
8369 : OGRFeature::ConstFieldIterator::~ConstFieldIterator() = default;
8370 :
8371 22 : const OGRFeature::FieldValue &OGRFeature::ConstFieldIterator::operator*() const
8372 : {
8373 22 : return m_poPrivate->m_oValue;
8374 : }
8375 :
8376 22 : OGRFeature::ConstFieldIterator &OGRFeature::ConstFieldIterator::operator++()
8377 : {
8378 22 : ++m_poPrivate->m_nPos;
8379 22 : m_poPrivate->m_oValue.m_poPrivate->m_nPos = m_poPrivate->m_nPos;
8380 22 : return *this;
8381 : }
8382 :
8383 24 : bool OGRFeature::ConstFieldIterator::operator!=(
8384 : const ConstFieldIterator &it) const
8385 : {
8386 24 : return m_poPrivate->m_nPos != it.m_poPrivate->m_nPos;
8387 : }
8388 :
8389 : //! @endcond
8390 :
8391 2 : OGRFeature::ConstFieldIterator OGRFeature::begin() const
8392 : {
8393 2 : return {this, 0};
8394 : }
8395 :
8396 2 : OGRFeature::ConstFieldIterator OGRFeature::end() const
8397 : {
8398 2 : return {this, GetFieldCount()};
8399 : }
8400 :
8401 : /************************************************************************/
8402 : /* OGRFeature::FieldValue */
8403 : /************************************************************************/
8404 :
8405 4 : OGRFeature::FieldValue::FieldValue(const OGRFeature *poFeature, int iFieldIndex)
8406 4 : : m_poPrivate(new Private(poFeature, iFieldIndex))
8407 : {
8408 4 : }
8409 :
8410 47 : OGRFeature::FieldValue::FieldValue(OGRFeature *poFeature, int iFieldIndex)
8411 47 : : m_poPrivate(new Private(poFeature, iFieldIndex))
8412 : {
8413 47 : }
8414 :
8415 14 : OGRFeature::FieldValue &OGRFeature::FieldValue::Assign(const FieldValue &oOther)
8416 : {
8417 27 : if (&oOther != this &&
8418 13 : !(m_poPrivate->m_poSelf == oOther.m_poPrivate->m_poSelf &&
8419 2 : m_poPrivate->m_nPos == oOther.m_poPrivate->m_nPos))
8420 : {
8421 12 : OGRFieldType eOtherType(oOther.GetType());
8422 12 : if (oOther.IsNull())
8423 1 : SetNull();
8424 11 : else if (oOther.IsUnset())
8425 1 : Unset();
8426 10 : else if (eOtherType == OFTInteger)
8427 2 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8428 : oOther.GetInteger());
8429 8 : else if (eOtherType == OFTInteger64)
8430 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8431 : oOther.GetInteger64());
8432 7 : else if (eOtherType == OFTReal)
8433 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8434 : oOther.GetDouble());
8435 6 : else if (eOtherType == OFTString)
8436 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8437 : oOther.GetString());
8438 5 : else if (eOtherType == OFTDate || eOtherType == OFTDateTime ||
8439 : eOtherType == OFTTime)
8440 : {
8441 1 : int nYear = 0;
8442 1 : int nMonth = 0;
8443 1 : int nDay = 0;
8444 1 : int nHour = 0;
8445 1 : int nMinute = 0;
8446 1 : float fSecond = 0.0f;
8447 1 : int nTZFlag = 0;
8448 1 : oOther.GetDateTime(&nYear, &nMonth, &nDay, &nHour, &nMinute,
8449 : &fSecond, &nTZFlag);
8450 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nYear, nMonth,
8451 : nDay, nHour, nMinute, fSecond,
8452 1 : nTZFlag);
8453 : }
8454 4 : else if (eOtherType == OFTStringList)
8455 : {
8456 2 : m_poPrivate->m_poSelf->SetField(
8457 1 : m_poPrivate->m_nPos,
8458 2 : oOther.m_poPrivate->m_poSelf->GetFieldAsStringList(
8459 1 : oOther.m_poPrivate->m_nPos));
8460 : }
8461 3 : else if (eOtherType == OFTIntegerList)
8462 : {
8463 1 : operator=(oOther.GetAsIntegerList());
8464 : }
8465 2 : else if (eOtherType == OFTInteger64List)
8466 : {
8467 1 : operator=(oOther.GetAsInteger64List());
8468 : }
8469 1 : else if (eOtherType == OFTRealList)
8470 : {
8471 1 : operator=(oOther.GetAsDoubleList());
8472 : }
8473 : }
8474 14 : return *this;
8475 : }
8476 :
8477 : OGRFeature::FieldValue &
8478 12 : OGRFeature::FieldValue::operator=(const FieldValue &oOther)
8479 : {
8480 12 : return Assign(oOther);
8481 : }
8482 :
8483 : //! @cond Doxygen_Suppress
8484 2 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(FieldValue &&oOther)
8485 : {
8486 2 : return Assign(oOther);
8487 : }
8488 :
8489 : //! @endcond
8490 :
8491 1 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(int nVal)
8492 : {
8493 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nVal);
8494 1 : return *this;
8495 : }
8496 :
8497 1 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(GIntBig nVal)
8498 : {
8499 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nVal);
8500 1 : return *this;
8501 : }
8502 :
8503 1 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(double dfVal)
8504 : {
8505 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, dfVal);
8506 1 : return *this;
8507 : }
8508 :
8509 2 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(const char *pszVal)
8510 : {
8511 2 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, pszVal);
8512 2 : return *this;
8513 : }
8514 :
8515 : OGRFeature::FieldValue &
8516 1 : OGRFeature::FieldValue::operator=(const std::string &osVal)
8517 : {
8518 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, osVal.c_str());
8519 1 : return *this;
8520 : }
8521 :
8522 : OGRFeature::FieldValue &
8523 3 : OGRFeature::FieldValue::operator=(const std::vector<int> &oArray)
8524 : {
8525 9 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8526 3 : static_cast<int>(oArray.size()),
8527 5 : oArray.empty() ? nullptr : oArray.data());
8528 3 : return *this;
8529 : }
8530 :
8531 : OGRFeature::FieldValue &
8532 3 : OGRFeature::FieldValue::operator=(const std::vector<GIntBig> &oArray)
8533 : {
8534 9 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8535 3 : static_cast<int>(oArray.size()),
8536 5 : oArray.empty() ? nullptr : oArray.data());
8537 3 : return *this;
8538 : }
8539 :
8540 : OGRFeature::FieldValue &
8541 3 : OGRFeature::FieldValue::operator=(const std::vector<double> &oArray)
8542 : {
8543 9 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8544 3 : static_cast<int>(oArray.size()),
8545 5 : oArray.empty() ? nullptr : oArray.data());
8546 3 : return *this;
8547 : }
8548 :
8549 : OGRFeature::FieldValue &
8550 2 : OGRFeature::FieldValue::operator=(const std::vector<std::string> &oArray)
8551 : {
8552 2 : CPLStringList aosList;
8553 4 : for (auto &&oStr : oArray)
8554 2 : aosList.AddString(oStr.c_str());
8555 2 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, aosList.List());
8556 4 : return *this;
8557 : }
8558 :
8559 : OGRFeature::FieldValue &
8560 2 : OGRFeature::FieldValue::operator=(CSLConstList papszValues)
8561 : {
8562 2 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, papszValues);
8563 2 : return *this;
8564 : }
8565 :
8566 1 : void OGRFeature::FieldValue::SetDateTime(int nYear, int nMonth, int nDay,
8567 : int nHour, int nMinute, float fSecond,
8568 : int nTZFlag)
8569 : {
8570 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nYear, nMonth, nDay,
8571 : nHour, nMinute, fSecond, nTZFlag);
8572 1 : }
8573 :
8574 2 : void OGRFeature::FieldValue::SetNull()
8575 : {
8576 2 : m_poPrivate->m_poSelf->SetFieldNull(m_poPrivate->m_nPos);
8577 2 : }
8578 :
8579 3 : void OGRFeature::FieldValue::clear()
8580 : {
8581 3 : m_poPrivate->m_poSelf->UnsetField(m_poPrivate->m_nPos);
8582 3 : }
8583 :
8584 : //! @cond Doxygen_Suppress
8585 : OGRFeature::FieldValue::~FieldValue() = default;
8586 :
8587 : //! @endcond
8588 :
8589 188 : int OGRFeature::FieldValue::GetIndex() const
8590 : {
8591 188 : return m_poPrivate->m_nPos;
8592 : }
8593 :
8594 89 : const OGRFieldDefn *OGRFeature::FieldValue::GetDefn() const
8595 : {
8596 89 : return m_poPrivate->m_poSelf->GetFieldDefnRef(GetIndex());
8597 : }
8598 :
8599 48 : const OGRField *OGRFeature::FieldValue::GetRawValue() const
8600 : {
8601 48 : return &(m_poPrivate->m_poSelf->pauFields[GetIndex()]);
8602 : }
8603 :
8604 15 : bool OGRFeature::FieldValue::IsUnset() const
8605 : {
8606 15 : return CPL_TO_BOOL(OGR_RawField_IsUnset(GetRawValue()));
8607 : }
8608 :
8609 15 : bool OGRFeature::FieldValue::IsNull() const
8610 : {
8611 15 : return CPL_TO_BOOL(OGR_RawField_IsNull(GetRawValue()));
8612 : }
8613 :
8614 5 : int OGRFeature::FieldValue::GetAsInteger() const
8615 : {
8616 5 : return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8617 5 : ->GetFieldAsInteger(GetIndex());
8618 : }
8619 :
8620 4 : GIntBig OGRFeature::FieldValue::GetAsInteger64() const
8621 : {
8622 4 : return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8623 4 : ->GetFieldAsInteger64(GetIndex());
8624 : }
8625 :
8626 4 : double OGRFeature::FieldValue::GetAsDouble() const
8627 : {
8628 4 : return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8629 4 : ->GetFieldAsDouble(GetIndex());
8630 : }
8631 :
8632 5 : const char *OGRFeature::FieldValue::GetAsString() const
8633 : {
8634 5 : return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8635 5 : ->GetFieldAsString(GetIndex());
8636 : }
8637 :
8638 2 : bool OGRFeature::FieldValue::GetDateTime(int *pnYear, int *pnMonth, int *pnDay,
8639 : int *pnHour, int *pnMinute,
8640 : float *pfSecond, int *pnTZFlag) const
8641 : {
8642 2 : return CPL_TO_BOOL(const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8643 : ->GetFieldAsDateTime(GetIndex(), pnYear, pnMonth,
8644 : pnDay, pnHour, pnMinute,
8645 2 : pfSecond, pnTZFlag));
8646 : }
8647 :
8648 2 : const std::vector<int> &OGRFeature::FieldValue::GetAsIntegerList() const
8649 : {
8650 2 : int nCount = 0;
8651 2 : auto &&panList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8652 2 : ->GetFieldAsIntegerList(GetIndex(), &nCount);
8653 2 : m_poPrivate->m_anList.assign(panList, panList + nCount);
8654 2 : return m_poPrivate->m_anList;
8655 : }
8656 :
8657 2 : const std::vector<GIntBig> &OGRFeature::FieldValue::GetAsInteger64List() const
8658 : {
8659 2 : int nCount = 0;
8660 2 : auto &&panList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8661 2 : ->GetFieldAsInteger64List(GetIndex(), &nCount);
8662 2 : m_poPrivate->m_anList64.assign(panList, panList + nCount);
8663 2 : return m_poPrivate->m_anList64;
8664 : }
8665 :
8666 2 : const std::vector<double> &OGRFeature::FieldValue::GetAsDoubleList() const
8667 : {
8668 2 : int nCount = 0;
8669 2 : auto &&panList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8670 2 : ->GetFieldAsDoubleList(GetIndex(), &nCount);
8671 2 : m_poPrivate->m_adfList.assign(panList, panList + nCount);
8672 2 : return m_poPrivate->m_adfList;
8673 : }
8674 :
8675 1 : const std::vector<std::string> &OGRFeature::FieldValue::GetAsStringList() const
8676 : {
8677 1 : auto &&papszList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8678 1 : ->GetFieldAsStringList(GetIndex());
8679 1 : m_poPrivate->m_aosList.clear();
8680 1 : if (papszList)
8681 : {
8682 3 : for (char **papszIter = papszList; *papszIter; ++papszIter)
8683 : {
8684 2 : m_poPrivate->m_aosList.emplace_back(*papszIter);
8685 : }
8686 : }
8687 1 : return m_poPrivate->m_aosList;
8688 : }
8689 :
8690 2 : OGRFeature::FieldValue::operator CSLConstList() const
8691 : {
8692 : return const_cast<CSLConstList>(
8693 2 : const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8694 2 : ->GetFieldAsStringList(GetIndex()));
8695 : }
8696 :
8697 16 : OGRRangeFieldDomain *OGRRangeFieldDomain::Clone() const
8698 : {
8699 : auto poDomain = new OGRRangeFieldDomain(
8700 16 : m_osName, m_osDescription, m_eFieldType, m_eFieldSubType, m_sMin,
8701 16 : m_bMinIsInclusive, m_sMax, m_bMaxIsInclusive);
8702 16 : poDomain->SetMergePolicy(m_eMergePolicy);
8703 16 : poDomain->SetSplitPolicy(m_eSplitPolicy);
8704 16 : return poDomain;
8705 : }
8706 :
8707 15 : OGRGlobFieldDomain *OGRGlobFieldDomain::Clone() const
8708 : {
8709 : auto poDomain = new OGRGlobFieldDomain(
8710 15 : m_osName, m_osDescription, m_eFieldType, m_eFieldSubType, m_osGlob);
8711 15 : poDomain->SetMergePolicy(m_eMergePolicy);
8712 15 : poDomain->SetSplitPolicy(m_eSplitPolicy);
8713 15 : return poDomain;
8714 : }
8715 : #if defined(__GNUC__)
8716 : #pragma GCC diagnostic pop
8717 : #endif
|