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