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