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 2053370 : 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 2053370 : m_poStyleTable(nullptr), m_pszTmpFieldValue(nullptr)
75 : {
76 2053370 : const_cast<OGRFeatureDefn *>(poDefnIn)->Reference();
77 :
78 2053370 : const int nFieldCount = poDefn->GetFieldCount();
79 2053370 : pauFields = static_cast<OGRField *>(
80 2053370 : VSI_MALLOC_VERBOSE(nFieldCount * sizeof(OGRField)));
81 :
82 2053370 : papoGeometries = static_cast<OGRGeometry **>(
83 2053370 : VSI_CALLOC_VERBOSE(poDefn->GetGeomFieldCount(), sizeof(OGRGeometry *)));
84 :
85 : // Initialize array to the unset special value.
86 2053370 : if (pauFields != nullptr)
87 : {
88 12963100 : for (int i = 0; i < nFieldCount; i++)
89 : {
90 10909700 : pauFields[i].Set.nMarker1 = OGRUnsetMarker;
91 10909700 : pauFields[i].Set.nMarker2 = OGRUnsetMarker;
92 10909700 : pauFields[i].Set.nMarker3 = OGRUnsetMarker;
93 : }
94 : }
95 2053370 : }
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 127901 : OGRFeatureH OGR_F_Create(OGRFeatureDefnH hDefn)
118 :
119 : {
120 127901 : VALIDATE_POINTER1(hDefn, "OGR_F_Create", nullptr);
121 127901 : return OGRFeature::ToHandle(
122 255802 : OGRFeature::CreateFeature(OGRFeatureDefn::FromHandle(hDefn)));
123 : }
124 :
125 : /************************************************************************/
126 : /* ~OGRFeature() */
127 : /************************************************************************/
128 :
129 5599150 : OGRFeature::~OGRFeature()
130 :
131 : {
132 2053340 : if (pauFields != nullptr)
133 : {
134 : // We can call GetFieldCountUnsafe() as the constructor has called
135 : // the regular GetFieldCount()
136 2053340 : const int nFieldcount = poDefn->GetFieldCountUnsafe();
137 12963500 : for (int i = 0; i < nFieldcount; i++)
138 : {
139 10910200 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefnUnsafe(i);
140 :
141 10910200 : if (!IsFieldSetAndNotNullUnsafe(i))
142 3412200 : continue;
143 :
144 7497980 : switch (poFDefn->GetType())
145 : {
146 4060210 : case OFTString:
147 4060210 : if (pauFields[i].String != nullptr)
148 4060110 : VSIFree(pauFields[i].String);
149 4060210 : 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 23765 : case OFTStringList:
157 23765 : CSLDestroy(pauFields[i].StringList.paList);
158 23765 : break;
159 :
160 81322 : case OFTIntegerList:
161 : case OFTInteger64List:
162 : case OFTRealList:
163 81322 : CPLFree(pauFields[i].IntegerList.paList);
164 81322 : break;
165 :
166 3273980 : default:
167 : // TODO(schwehr): Add support for wide strings.
168 3273980 : break;
169 : }
170 : }
171 : }
172 :
173 2053340 : if (papoGeometries != nullptr)
174 : {
175 2053340 : const int nGeomFieldCount = poDefn->GetGeomFieldCount();
176 :
177 3361790 : for (int i = 0; i < nGeomFieldCount; i++)
178 : {
179 1308450 : delete papoGeometries[i];
180 : }
181 : }
182 :
183 2053340 : if (poDefn)
184 2053340 : const_cast<OGRFeatureDefn *>(poDefn)->Release();
185 :
186 2053340 : CPLFree(pauFields);
187 2053340 : CPLFree(papoGeometries);
188 2053340 : CPLFree(m_pszStyleString);
189 2053340 : CPLFree(m_pszTmpFieldValue);
190 2053340 : CPLFree(m_pszNativeData);
191 2053340 : CPLFree(m_pszNativeMediaType);
192 3545810 : }
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 214968 : void OGR_F_Destroy(OGRFeatureH hFeat)
212 :
213 : {
214 214968 : delete OGRFeature::FromHandle(hFeat);
215 214968 : }
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 483090 : OGRFeature *OGRFeature::CreateFeature(const OGRFeatureDefn *poDefn)
238 :
239 : {
240 483090 : OGRFeature *poFeature = new (std::nothrow) OGRFeature(poDefn);
241 483090 : if (poFeature == nullptr)
242 0 : return nullptr;
243 :
244 0 : if ((poFeature->pauFields == nullptr &&
245 966180 : poDefn->GetFieldCountUnsafe() != 0) ||
246 483090 : (poFeature->papoGeometries == nullptr &&
247 0 : poDefn->GetGeomFieldCount() != 0))
248 : {
249 0 : delete poFeature;
250 0 : return nullptr;
251 : }
252 :
253 483090 : 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 66277 : void OGRFeature::DestroyFeature(OGRFeature *poFeature)
275 :
276 : {
277 66277 : delete poFeature;
278 66277 : }
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 26653 : void OGRFeature::SetFDefnUnsafe(OGRFeatureDefn *poNewFDefn)
372 : {
373 26653 : poNewFDefn->Reference();
374 26653 : const_cast<OGRFeatureDefn *>(poDefn)->Release();
375 26653 : poDefn = poNewFDefn;
376 26653 : }
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 47990 : OGRFeatureDefnH OGR_F_GetDefnRef(OGRFeatureH hFeat)
420 :
421 : {
422 47990 : VALIDATE_POINTER1(hFeat, "OGR_F_GetDefnRef", nullptr);
423 :
424 47990 : return OGRFeatureDefn::ToHandle(const_cast<OGRFeatureDefn *>(
425 95980 : 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 789700 : OGRErr OGRFeature::SetGeometryDirectly(OGRGeometry *poGeomIn)
456 :
457 : {
458 789700 : if (poGeomIn == GetGeometryRef())
459 : {
460 872 : return OGRERR_NONE;
461 : }
462 :
463 788828 : 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 39560 : OGRErr OGR_F_SetGeometryDirectly(OGRFeatureH hFeat, OGRGeometryH hGeom)
494 :
495 : {
496 39560 : VALIDATE_POINTER1(hFeat, "OGR_F_SetGeometryDirectly", OGRERR_FAILURE);
497 :
498 39560 : return OGRFeature::FromHandle(hFeat)->SetGeometryDirectly(
499 39560 : 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 236879 : OGRErr OGRFeature::SetGeometry(const OGRGeometry *poGeomIn)
530 :
531 : {
532 236879 : if (GetGeomFieldCount() < 1)
533 2 : return OGRERR_FAILURE;
534 :
535 236877 : 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 236508 : OGRErr OGR_F_SetGeometry(OGRFeatureH hFeat, OGRGeometryH hGeom)
565 :
566 : {
567 236508 : VALIDATE_POINTER1(hFeat, "OGR_F_SetGeometry", OGRERR_FAILURE);
568 :
569 473016 : return OGRFeature::FromHandle(hFeat)->SetGeometry(
570 473016 : 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 334814 : OGRErr OGRFeature::SetGeometry(std::unique_ptr<OGRGeometry> poGeomIn)
599 :
600 : {
601 334814 : 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 10214 : OGRGeometry *OGRFeature::StealGeometry(int iGeomField)
650 :
651 : {
652 10214 : if (iGeomField >= 0 && iGeomField < GetGeomFieldCount())
653 : {
654 10213 : OGRGeometry *poReturn = papoGeometries[iGeomField];
655 10213 : papoGeometries[iGeomField] = nullptr;
656 10213 : 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 2009080 : OGRGeometry *OGRFeature::GetGeometryRef()
738 :
739 : {
740 2009080 : if (GetGeomFieldCount() > 0)
741 1998020 : 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 267795 : const OGRGeometry *OGRFeature::GetGeometryRef() const
759 :
760 : {
761 267795 : if (GetGeomFieldCount() > 0)
762 264006 : return GetGeomFieldRef(0);
763 :
764 3789 : 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 39893 : OGRGeometryH OGR_F_GetGeometryRef(OGRFeatureH hFeat)
784 :
785 : {
786 39893 : VALIDATE_POINTER1(hFeat, "OGR_F_GetGeometryRef", nullptr);
787 :
788 39893 : OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
789 39893 : OGRGeometry *poGeom = poFeature->GetGeometryRef();
790 :
791 39894 : 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 39893 : 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 3444070 : OGRGeometry *OGRFeature::GetGeomFieldRef(int iField)
822 :
823 : {
824 3444070 : if (iField < 0 || iField >= GetGeomFieldCount())
825 8 : return nullptr;
826 : else
827 3444060 : 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 288273 : const OGRGeometry *OGRFeature::GetGeomFieldRef(int iField) const
841 :
842 : {
843 288273 : if (iField < 0 || iField >= GetGeomFieldCount())
844 23 : return nullptr;
845 : else
846 288250 : 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 248096 : OGRErr OGRFeature::SetGeomField(int iField, const OGRGeometry *poGeomIn)
1022 :
1023 : {
1024 248096 : if (iField < 0 || iField >= GetGeomFieldCount())
1025 1 : return OGRERR_FAILURE;
1026 :
1027 248095 : if (papoGeometries[iField] != poGeomIn)
1028 : {
1029 247110 : delete papoGeometries[iField];
1030 :
1031 247110 : if (poGeomIn != nullptr)
1032 246986 : papoGeometries[iField] = poGeomIn->clone();
1033 : else
1034 124 : papoGeometries[iField] = nullptr;
1035 : }
1036 :
1037 : // TODO(schwehr): Verify that the geometry matches the defn's type.
1038 :
1039 248095 : 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 1170470 : OGRErr OGRFeature::SetGeomField(int iField,
1095 : std::unique_ptr<OGRGeometry> poGeomIn)
1096 :
1097 : {
1098 1170470 : if (iField < 0 || iField >= GetGeomFieldCount())
1099 : {
1100 5444 : return OGRERR_FAILURE;
1101 : }
1102 :
1103 1165020 : if (papoGeometries[iField] != poGeomIn.get())
1104 : {
1105 1164770 : delete papoGeometries[iField];
1106 1164770 : papoGeometries[iField] = poGeomIn.release();
1107 : }
1108 :
1109 1165020 : 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 346150 : OGRFeature *OGRFeature::Clone() const
1129 :
1130 : {
1131 346150 : OGRFeature *poNew = CreateFeature(poDefn);
1132 346150 : if (poNew == nullptr)
1133 0 : return nullptr;
1134 :
1135 346150 : if (!CopySelfTo(poNew))
1136 : {
1137 0 : delete poNew;
1138 0 : return nullptr;
1139 : }
1140 :
1141 346150 : 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 349846 : bool OGRFeature::CopySelfTo(OGRFeature *poNew) const
1183 : {
1184 349846 : const int nFieldCount = poDefn->GetFieldCountUnsafe();
1185 4582300 : for (int i = 0; i < nFieldCount; i++)
1186 : {
1187 4232450 : if (!poNew->SetFieldInternal(i, pauFields + i))
1188 : {
1189 0 : return false;
1190 : }
1191 : }
1192 349846 : if (poNew->papoGeometries)
1193 : {
1194 395372 : for (int i = 0; i < poDefn->GetGeomFieldCount(); i++)
1195 : {
1196 45526 : if (papoGeometries[i] != nullptr)
1197 : {
1198 42162 : poNew->papoGeometries[i] = papoGeometries[i]->clone();
1199 42162 : if (poNew->papoGeometries[i] == nullptr)
1200 : {
1201 0 : return false;
1202 : }
1203 : }
1204 : }
1205 : }
1206 :
1207 349846 : 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 349846 : poNew->SetFID(GetFID());
1217 :
1218 349846 : 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 349846 : 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 349846 : 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 113069 : int OGR_F_GetFieldCount(OGRFeatureH hFeat)
1271 :
1272 : {
1273 113069 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldCount", 0);
1274 :
1275 113069 : 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 189804 : OGRFieldDefnH OGR_F_GetFieldDefnRef(OGRFeatureH hFeat, int i)
1312 :
1313 : {
1314 189804 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldDefnRef", nullptr);
1315 :
1316 189804 : OGRFeature *poFeat = OGRFeature::FromHandle(hFeat);
1317 :
1318 189804 : return OGRFieldDefn::ToHandle(
1319 189804 : 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 406653 : int OGRFeature::IsFieldSet(int iField) const
1515 :
1516 : {
1517 406653 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
1518 406653 : 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 405593 : 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 103195 : int OGR_F_IsFieldSet(OGRFeatureH hFeat, int iField)
1566 :
1567 : {
1568 103195 : VALIDATE_POINTER1(hFeat, "OGR_F_IsFieldSet", 0);
1569 :
1570 103195 : const OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
1571 103195 : 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 103195 : 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 280337 : bool OGRFeature::IsFieldNull(int iField) const
1667 :
1668 : {
1669 280337 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
1670 280337 : if (iSpecialField >= 0)
1671 : {
1672 : // FIXME?
1673 0 : return false;
1674 : }
1675 : else
1676 : {
1677 280337 : 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 102328 : int OGR_F_IsFieldNull(OGRFeatureH hFeat, int iField)
1698 :
1699 : {
1700 102328 : VALIDATE_POINTER1(hFeat, "OGR_F_IsFieldNull", 0);
1701 :
1702 102328 : const OGRFeature *poFeature = OGRFeature::FromHandle(hFeat);
1703 102328 : 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 102328 : 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 522248 : bool OGRFeature::IsFieldSetAndNotNull(int iField) const
1728 :
1729 : {
1730 522248 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
1731 522248 : if (iSpecialField >= 0)
1732 : {
1733 1060 : return CPL_TO_BOOL(IsFieldSet(iField));
1734 : }
1735 : else
1736 : {
1737 521188 : 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 173642 : int OGRFeature::GetFieldAsInteger(int iField) const
1996 :
1997 : {
1998 173642 : int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
1999 173642 : 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 173623 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
2033 :
2034 173623 : if (poFDefn == nullptr)
2035 4 : return 0;
2036 :
2037 173619 : if (!IsFieldSetAndNotNullUnsafe(iField))
2038 14119 : return 0;
2039 :
2040 159500 : const OGRFieldType eType = poFDefn->GetType();
2041 159500 : if (eType == OFTInteger)
2042 : {
2043 130257 : 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 29495 : GIntBig OGRFeature::GetFieldAsInteger64(int iField) const
2139 :
2140 : {
2141 29495 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
2142 29495 : 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 28694 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
2162 :
2163 28694 : if (poFDefn == nullptr)
2164 0 : return 0;
2165 :
2166 28694 : if (!IsFieldSetAndNotNullUnsafe(iField))
2167 27 : return 0;
2168 :
2169 28667 : OGRFieldType eType = poFDefn->GetType();
2170 28667 : if (eType == OFTInteger)
2171 : {
2172 11740 : return static_cast<GIntBig>(pauFields[iField].Integer);
2173 : }
2174 16927 : else if (eType == OFTInteger64)
2175 : {
2176 16823 : 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 1503 : GIntBig OGR_F_GetFieldAsInteger64(OGRFeatureH hFeat, int iField)
2217 :
2218 : {
2219 1503 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsInteger64", 0);
2220 :
2221 1503 : 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 134173 : double OGRFeature::GetFieldAsDouble(int iField) const
2256 :
2257 : {
2258 134173 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
2259 134173 : 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 134148 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
2278 :
2279 134148 : if (poFDefn == nullptr)
2280 5 : return 0.0;
2281 :
2282 134143 : if (!IsFieldSetAndNotNullUnsafe(iField))
2283 96 : return 0.0;
2284 :
2285 134047 : const OGRFieldType eType = poFDefn->GetType();
2286 134047 : if (eType == OFTReal)
2287 : {
2288 69869 : 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 2554 : double OGR_F_GetFieldAsDouble(OGRFeatureH hFeat, int iField)
2329 :
2330 : {
2331 2554 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsDouble", 0);
2332 :
2333 2554 : 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 249338 : const char *OGRFeature::GetFieldAsString(int iField) const
2441 :
2442 : {
2443 249338 : CPLFree(m_pszTmpFieldValue);
2444 249338 : m_pszTmpFieldValue = nullptr;
2445 :
2446 249338 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
2447 249338 : 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 249065 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
2504 :
2505 249065 : if (poFDefn == nullptr)
2506 3 : return "";
2507 :
2508 249062 : if (!IsFieldSetAndNotNullUnsafe(iField))
2509 6166 : return "";
2510 :
2511 242896 : OGRFieldType eType = poFDefn->GetType();
2512 242896 : if (eType == OFTString)
2513 : {
2514 222705 : if (pauFields[iField].String == nullptr)
2515 0 : return "";
2516 : else
2517 222705 : return pauFields[iField].String;
2518 : }
2519 20191 : 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 12335 : 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 11285 : else if (eType == OFTReal)
2535 : {
2536 2676 : char szFormat[32] = {};
2537 2676 : constexpr int TEMP_BUFFER_SIZE = 80;
2538 2676 : char szTempBuffer[TEMP_BUFFER_SIZE] = {};
2539 :
2540 2676 : 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 1949 : 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 1928 : strcpy(szFormat, "%.15g");
2559 :
2560 1928 : CPLsnprintf(szTempBuffer, TEMP_BUFFER_SIZE, szFormat,
2561 1928 : pauFields[iField].Real);
2562 : }
2563 : }
2564 :
2565 2676 : m_pszTmpFieldValue = VSI_STRDUP_VERBOSE(szTempBuffer);
2566 2676 : if (m_pszTmpFieldValue == nullptr)
2567 0 : return "";
2568 2676 : 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 12361 : const char *OGR_F_GetFieldAsString(OGRFeatureH hFeat, int iField)
2757 :
2758 : {
2759 12361 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFieldAsString", nullptr);
2760 :
2761 12361 : 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 11369 : char **OGRFeature::GetFieldAsStringList(int iField) const
3171 :
3172 : {
3173 11369 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3174 :
3175 11369 : if (poFDefn == nullptr)
3176 0 : return nullptr;
3177 :
3178 11369 : if (!IsFieldSetAndNotNullUnsafe(iField))
3179 92 : return nullptr;
3180 :
3181 11277 : if (poFDefn->GetType() == OFTStringList)
3182 : {
3183 11277 : 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 1723460 : static int OGRFeatureGetIntegerValue(const OGRFeatureDefn *poDefn,
3469 : const OGRFieldDefn *poFDefn, int nValue)
3470 : {
3471 1723460 : 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 1723450 : 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 1723460 : 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 15098 : char *OGRFeature::GetFieldAsSerializedJSon(int iField) const
3517 :
3518 : {
3519 15098 : const int iSpecialField = iField - poDefn->GetFieldCountUnsafe();
3520 15098 : if (iSpecialField >= 0)
3521 : {
3522 0 : return nullptr;
3523 : }
3524 :
3525 15098 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3526 :
3527 15098 : if (poFDefn == nullptr)
3528 0 : return nullptr;
3529 :
3530 15098 : if (!IsFieldSetAndNotNullUnsafe(iField))
3531 0 : return nullptr;
3532 :
3533 15098 : char *pszRet = nullptr;
3534 15098 : OGRFieldType eType = poFDefn->GetType();
3535 15098 : if (eType == OFTString && poFDefn->GetSubType() == OFSTJSON)
3536 : {
3537 15 : if (pauFields[iField].String[0] != '[' &&
3538 5 : pauFields[iField].String[0] != '{' &&
3539 3 : strcmp(pauFields[iField].String, "true") != 0 &&
3540 12 : 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 4 : pszRet = CPLStrdup(pauFields[iField].String);
3553 : }
3554 : }
3555 15093 : else if (eType == OFTStringList)
3556 : {
3557 5031 : char **papszValues = GetFieldAsStringList(iField);
3558 5031 : if (papszValues == nullptr)
3559 : {
3560 1 : pszRet = CPLStrdup("[]");
3561 : }
3562 : else
3563 : {
3564 5030 : json_object *poObj = json_object_new_array();
3565 15091 : for (int i = 0; papszValues[i] != nullptr; i++)
3566 : {
3567 10061 : json_object_array_add(poObj,
3568 10061 : json_object_new_string(papszValues[i]));
3569 : }
3570 5030 : pszRet = CPLStrdup(json_object_to_json_string(poObj));
3571 5030 : 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 15098 : 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 1651900 : void OGRFeature::SetField(int iField, int nValue)
3666 :
3667 : {
3668 1651900 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3669 :
3670 1651900 : if (poFDefn == nullptr)
3671 0 : return;
3672 :
3673 1651900 : OGRFieldType eType = poFDefn->GetType();
3674 1651900 : if (eType == OFTInteger)
3675 : {
3676 3297640 : pauFields[iField].Integer =
3677 1648820 : OGRFeatureGetIntegerValue(poDefn, poFDefn, nValue);
3678 1648820 : pauFields[iField].Set.nMarker2 = 0;
3679 1648820 : 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 4815 : void OGR_F_SetFieldInteger(OGRFeatureH hFeat, int iField, int nValue)
3758 :
3759 : {
3760 4815 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldInteger");
3761 :
3762 4815 : 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 96299 : void OGRFeature::SetField(int iField, GIntBig nValue)
3806 :
3807 : {
3808 96299 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3809 :
3810 96299 : if (poFDefn == nullptr)
3811 0 : return;
3812 :
3813 96299 : OGRFieldType eType = poFDefn->GetType();
3814 96299 : if (eType == OFTInteger)
3815 : {
3816 175680 : const int nVal32 = nValue < INT_MIN ? INT_MIN
3817 87840 : : nValue > INT_MAX ? INT_MAX
3818 : : static_cast<int>(nValue);
3819 :
3820 87840 : 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 87840 : SetField(iField, nVal32);
3830 : }
3831 8459 : else if (eType == OFTInteger64)
3832 : {
3833 7691 : pauFields[iField].Integer64 = nValue;
3834 : }
3835 768 : else if (eType == OFTReal)
3836 : {
3837 648 : 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 1296 : if (pauFields[iField].Real >=
3842 1294 : static_cast<double>(std::numeric_limits<int64_t>::max()) ||
3843 646 : 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 85737 : void OGR_F_SetFieldInteger64(OGRFeatureH hFeat, int iField, GIntBig nValue)
3933 :
3934 : {
3935 85737 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldInteger64");
3936 :
3937 85737 : 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 71475 : void OGRFeature::SetField(int iField, double dfValue)
3982 :
3983 : {
3984 71475 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
3985 :
3986 71475 : if (poFDefn == nullptr)
3987 0 : return;
3988 :
3989 71475 : const OGRFieldType eType = poFDefn->GetType();
3990 71475 : 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 57564 : pauFields[iField].Real = dfValue;
4001 : }
4002 13911 : else if (eType == OFTInteger)
4003 : {
4004 13473 : constexpr int nMin = std::numeric_limits<int>::min();
4005 13473 : 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 13471 : constexpr int nMax = std::numeric_limits<int>::max();
4017 26942 : const int nVal = dfValue < nMin ? nMin
4018 13471 : : dfValue > nMax ? nMax
4019 13462 : : static_cast<int>(dfValue);
4020 26942 : pauFields[iField].Integer =
4021 13471 : OGRFeatureGetIntegerValue(poDefn, poFDefn, nVal);
4022 13471 : 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 13473 : pauFields[iField].Set.nMarker2 = 0;
4032 13473 : 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 2130 : void OGR_F_SetFieldDouble(OGRFeatureH hFeat, int iField, double dfValue)
4133 :
4134 : {
4135 2130 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDouble");
4136 :
4137 2130 : 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 2388290 : void OGRFeature::SetField(int iField, const char *pszValue)
4182 :
4183 : {
4184 : static int bWarn = -1;
4185 2388290 : if (bWarn < 0)
4186 396 : bWarn = CPLTestBool(
4187 : CPLGetConfigOption("OGR_SETFIELD_NUMERIC_WARNING", "YES"));
4188 :
4189 2388290 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
4190 2388290 : if (poFDefn == nullptr)
4191 1 : return;
4192 :
4193 2388280 : char *pszLast = nullptr;
4194 :
4195 2388280 : OGRFieldType eType = poFDefn->GetType();
4196 2388280 : if (eType == OFTString)
4197 : {
4198 2142360 : if (IsFieldSetAndNotNullUnsafe(iField))
4199 4444 : CPLFree(pauFields[iField].String);
4200 :
4201 2142360 : pauFields[iField].String = VSI_STRDUP_VERBOSE(pszValue ? pszValue : "");
4202 2142360 : if (pauFields[iField].String == nullptr)
4203 : {
4204 0 : OGR_RawField_SetUnset(&pauFields[iField]);
4205 : }
4206 : }
4207 245924 : else if (eType == OFTInteger)
4208 : {
4209 46102 : if (poFDefn->GetSubType() == OFSTBoolean)
4210 : {
4211 100 : constexpr char DIGIT_ZERO = '0';
4212 100 : if ((pszValue[0] == '1' && pszValue[1] == '\0') ||
4213 16 : EQUAL(pszValue, "true") || EQUAL(pszValue, "on") ||
4214 12 : EQUAL(pszValue, "yes"))
4215 : {
4216 89 : pauFields[iField].Integer = 1;
4217 89 : pauFields[iField].Set.nMarker2 = 0;
4218 89 : 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 46002 : errno = 0;
4258 :
4259 46002 : long long nVal64 = std::strtoll(pszValue, &pszLast, 10);
4260 91989 : int nVal32 = nVal64 > INT_MAX ? INT_MAX
4261 45987 : : nVal64 < INT_MIN ? INT_MIN
4262 : : static_cast<int>(nVal64);
4263 92004 : pauFields[iField].Integer =
4264 46002 : OGRFeatureGetIntegerValue(poDefn, poFDefn, nVal32);
4265 46002 : if (bWarn && pauFields[iField].Integer == nVal32 &&
4266 46002 : (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 46002 : pauFields[iField].Set.nMarker2 = 0;
4273 46002 : pauFields[iField].Set.nMarker3 = 0;
4274 : }
4275 : }
4276 199822 : else if (eType == OFTInteger64)
4277 : {
4278 93863 : pauFields[iField].Integer64 = CPLAtoGIntBigEx(pszValue, bWarn, nullptr);
4279 93863 : pauFields[iField].Set.nMarker3 = 0;
4280 : }
4281 105959 : else if (eType == OFTReal)
4282 : {
4283 93731 : pauFields[iField].Real = CPLStrtod(pszValue, &pszLast);
4284 93731 : 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 : /* OGR_F_SetFieldString() */
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 function is the same as the C++ method OGRFeature::SetField().
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 hFeat handle to the feature that owned the field.
4488 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
4489 : * @param pszValue the value to assign.
4490 : */
4491 :
4492 12336 : void OGR_F_SetFieldString(OGRFeatureH hFeat, int iField, const char *pszValue)
4493 :
4494 : {
4495 12336 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldString");
4496 :
4497 12336 : OGRFeature::FromHandle(hFeat)->SetField(iField, pszValue);
4498 : }
4499 :
4500 : /************************************************************************/
4501 : /* SetField() */
4502 : /************************************************************************/
4503 :
4504 : /**
4505 : * \fn OGRFeature::SetField( const char* pszFName, int nCount, const int
4506 : * *panValues ) \brief Set field to list of integers value.
4507 : *
4508 : * This method currently on has an effect of OFTIntegerList, OFTInteger64List
4509 : * and OFTRealList fields.
4510 : *
4511 : * @note This method has only an effect on the in-memory feature object. If
4512 : * this object comes from a layer and the modifications must be serialized back
4513 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4514 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4515 : *
4516 : * @param pszFName the name of the field to set.
4517 : * @param nCount the number of values in the list being assigned.
4518 : * @param panValues the values to assign.
4519 : */
4520 :
4521 : /**
4522 : * \brief Set field to list of integers value.
4523 : *
4524 : * This method currently on has an effect of OFTIntegerList, OFTInteger64List
4525 : * and OFTRealList fields.
4526 : *
4527 : * This method is the same as the C function OGR_F_SetFieldIntegerList().
4528 : *
4529 : * @note This method has only an effect on the in-memory feature object. If
4530 : * this object comes from a layer and the modifications must be serialized back
4531 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4532 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4533 : *
4534 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4535 : * @param nCount the number of values in the list being assigned.
4536 : * @param panValues the values to assign.
4537 : */
4538 :
4539 32608 : void OGRFeature::SetField(int iField, int nCount, const int *panValues)
4540 :
4541 : {
4542 32608 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
4543 :
4544 32608 : if (poFDefn == nullptr)
4545 0 : return;
4546 :
4547 32608 : OGRFieldType eType = poFDefn->GetType();
4548 32608 : if (eType == OFTIntegerList)
4549 : {
4550 : OGRField uField;
4551 32598 : int *panValuesMod = nullptr;
4552 :
4553 57930 : if (poFDefn->GetSubType() == OFSTBoolean ||
4554 25332 : poFDefn->GetSubType() == OFSTInt16)
4555 : {
4556 21654 : for (int i = 0; i < nCount; i++)
4557 : {
4558 : int nVal =
4559 13966 : OGRFeatureGetIntegerValue(poDefn, poFDefn, panValues[i]);
4560 13966 : if (panValues[i] != nVal)
4561 : {
4562 2 : if (panValuesMod == nullptr)
4563 : {
4564 : panValuesMod = static_cast<int *>(
4565 2 : VSI_MALLOC_VERBOSE(nCount * sizeof(int)));
4566 2 : if (panValuesMod == nullptr)
4567 0 : return;
4568 2 : if (nCount > 0)
4569 2 : memcpy(panValuesMod, panValues,
4570 2 : nCount * sizeof(int));
4571 : }
4572 2 : panValuesMod[i] = nVal;
4573 : }
4574 : }
4575 : }
4576 :
4577 32598 : uField.IntegerList.nCount = nCount;
4578 32598 : uField.Set.nMarker2 = 0;
4579 32598 : uField.Set.nMarker3 = 0;
4580 32598 : uField.IntegerList.paList =
4581 32598 : panValuesMod ? panValuesMod : const_cast<int *>(panValues);
4582 :
4583 32598 : SetField(iField, &uField);
4584 32598 : CPLFree(panValuesMod);
4585 : }
4586 10 : else if (eType == OFTInteger64List)
4587 : {
4588 2 : std::vector<GIntBig> anValues;
4589 1 : anValues.reserve(nCount);
4590 4 : for (int i = 0; i < nCount; i++)
4591 3 : anValues.push_back(panValues[i]);
4592 1 : if (nCount > 0)
4593 1 : SetField(iField, nCount, &anValues[0]);
4594 : }
4595 9 : else if (eType == OFTRealList)
4596 : {
4597 2 : std::vector<double> adfValues;
4598 1 : adfValues.reserve(nCount);
4599 4 : for (int i = 0; i < nCount; i++)
4600 3 : adfValues.push_back(static_cast<double>(panValues[i]));
4601 1 : if (nCount > 0)
4602 1 : SetField(iField, nCount, &adfValues[0]);
4603 : }
4604 8 : else if ((eType == OFTInteger || eType == OFTInteger64 ||
4605 3 : eType == OFTReal) &&
4606 : nCount == 1)
4607 : {
4608 3 : SetField(iField, panValues[0]);
4609 : }
4610 5 : else if (eType == OFTStringList)
4611 : {
4612 : char **papszValues = static_cast<char **>(
4613 1 : VSI_MALLOC_VERBOSE((nCount + 1) * sizeof(char *)));
4614 1 : if (papszValues == nullptr)
4615 0 : return;
4616 4 : for (int i = 0; i < nCount; i++)
4617 3 : papszValues[i] = VSI_STRDUP_VERBOSE(CPLSPrintf("%d", panValues[i]));
4618 1 : papszValues[nCount] = nullptr;
4619 1 : SetField(iField, papszValues);
4620 1 : CSLDestroy(papszValues);
4621 : }
4622 : }
4623 :
4624 : /************************************************************************/
4625 : /* OGR_F_SetFieldIntegerList() */
4626 : /************************************************************************/
4627 :
4628 : /**
4629 : * \brief Set field to list of integers value.
4630 : *
4631 : * This function currently on has an effect of OFTIntegerList, OFTInteger64List
4632 : * and OFTRealList fields.
4633 : *
4634 : * This function is the same as the C++ method OGRFeature::SetField().
4635 : *
4636 : * @note This method has only an effect on the in-memory feature object. If
4637 : * this object comes from a layer and the modifications must be serialized back
4638 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4639 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4640 : *
4641 : * @param hFeat handle to the feature that owned the field.
4642 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4643 : * @param nCount the number of values in the list being assigned.
4644 : * @param panValues the values to assign.
4645 : */
4646 :
4647 9 : void OGR_F_SetFieldIntegerList(OGRFeatureH hFeat, int iField, int nCount,
4648 : const int *panValues)
4649 :
4650 : {
4651 9 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldIntegerList");
4652 :
4653 9 : OGRFeature::FromHandle(hFeat)->SetField(iField, nCount, panValues);
4654 : }
4655 :
4656 : /************************************************************************/
4657 : /* SetField() */
4658 : /************************************************************************/
4659 :
4660 : /**
4661 : * \fn OGRFeature::SetField( const char* pszFName, int nCount, const GIntBig
4662 : * *panValues )
4663 : * \brief Set field to list of 64 bit integers value.
4664 : *
4665 : * This method currently on has an effect of OFTIntegerList, OFTInteger64List
4666 : * and OFTRealList fields.
4667 : *
4668 : * @note This method has only an effect on the in-memory feature object. If
4669 : * this object comes from a layer and the modifications must be serialized back
4670 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4671 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4672 : *
4673 : * @param pszFName the name of the field to set.
4674 : * @param nCount the number of values in the list being assigned.
4675 : * @param panValues the values to assign.
4676 : */
4677 :
4678 : /**
4679 : * \brief Set field to list of 64 bit integers value.
4680 : *
4681 : * This method currently on has an effect of OFTIntegerList, OFTInteger64List
4682 : * and OFTRealList fields.
4683 : *
4684 : * This method is the same as the C function OGR_F_SetFieldInteger64List().
4685 : *
4686 : * @note This method has only an effect on the in-memory feature object. If
4687 : * this object comes from a layer and the modifications must be serialized back
4688 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4689 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4690 : *
4691 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4692 : * @param nCount the number of values in the list being assigned.
4693 : * @param panValues the values to assign.
4694 : */
4695 :
4696 12864 : void OGRFeature::SetField(int iField, int nCount, const GIntBig *panValues)
4697 :
4698 : {
4699 12864 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
4700 :
4701 12864 : if (poFDefn == nullptr)
4702 0 : return;
4703 :
4704 12864 : OGRFieldType eType = poFDefn->GetType();
4705 12864 : if (eType == OFTIntegerList)
4706 : {
4707 150 : std::vector<int> anValues;
4708 :
4709 406 : for (int i = 0; i < nCount; i++)
4710 : {
4711 331 : const GIntBig nValue = panValues[i];
4712 662 : const int nVal32 = nValue < INT_MIN ? INT_MIN
4713 331 : : nValue > INT_MAX ? INT_MAX
4714 : : static_cast<int>(nValue);
4715 :
4716 331 : if (nVal32 != nValue)
4717 : {
4718 2 : CPLError(
4719 : CE_Warning, CPLE_AppDefined,
4720 : "Field %s.%s: Integer overflow occurred when trying to "
4721 : "set %" PRId64 " as 32 bit value.",
4722 1 : poDefn->GetName(), poFDefn->GetNameRef(),
4723 : static_cast<int64_t>(nValue));
4724 : }
4725 331 : anValues.push_back(nVal32);
4726 : }
4727 75 : if (nCount > 0)
4728 75 : SetField(iField, nCount, &anValues[0]);
4729 : }
4730 12789 : else if (eType == OFTInteger64List)
4731 : {
4732 : OGRField uField;
4733 12779 : uField.Integer64List.nCount = nCount;
4734 12779 : uField.Set.nMarker2 = 0;
4735 12779 : uField.Set.nMarker3 = 0;
4736 12779 : uField.Integer64List.paList = const_cast<GIntBig *>(panValues);
4737 :
4738 12779 : SetField(iField, &uField);
4739 : }
4740 10 : else if (eType == OFTRealList)
4741 : {
4742 4 : std::vector<double> adfValues;
4743 2 : adfValues.reserve(nCount);
4744 103 : for (int i = 0; i < nCount; i++)
4745 101 : adfValues.push_back(static_cast<double>(panValues[i]));
4746 2 : if (nCount > 0)
4747 2 : SetField(iField, nCount, &adfValues[0]);
4748 : }
4749 8 : else if ((eType == OFTInteger || eType == OFTInteger64 ||
4750 3 : eType == OFTReal) &&
4751 : nCount == 1)
4752 : {
4753 3 : SetField(iField, panValues[0]);
4754 : }
4755 5 : else if (eType == OFTStringList)
4756 : {
4757 : char **papszValues = static_cast<char **>(
4758 1 : VSI_MALLOC_VERBOSE((nCount + 1) * sizeof(char *)));
4759 1 : if (papszValues == nullptr)
4760 0 : return;
4761 2 : for (int i = 0; i < nCount; i++)
4762 2 : papszValues[i] =
4763 1 : VSI_STRDUP_VERBOSE(CPLSPrintf(CPL_FRMT_GIB, panValues[i]));
4764 1 : papszValues[nCount] = nullptr;
4765 1 : SetField(iField, papszValues);
4766 1 : CSLDestroy(papszValues);
4767 : }
4768 : }
4769 :
4770 : /************************************************************************/
4771 : /* OGR_F_SetFieldInteger64List() */
4772 : /************************************************************************/
4773 :
4774 : /**
4775 : * \brief Set field to list of 64 bit integers value.
4776 : *
4777 : * This function currently on has an effect of OFTIntegerList, OFTInteger64List
4778 : * and OFTRealList fields.
4779 : *
4780 : * This function is the same as the C++ method OGRFeature::SetField().
4781 : *
4782 : * @note This method has only an effect on the in-memory feature object. If
4783 : * this object comes from a layer and the modifications must be serialized back
4784 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4785 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4786 : *
4787 : * @param hFeat handle to the feature that owned the field.
4788 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4789 : * @param nCount the number of values in the list being assigned.
4790 : * @param panValues the values to assign.
4791 : */
4792 :
4793 124 : void OGR_F_SetFieldInteger64List(OGRFeatureH hFeat, int iField, int nCount,
4794 : const GIntBig *panValues)
4795 :
4796 : {
4797 124 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldInteger64List");
4798 :
4799 124 : OGRFeature::FromHandle(hFeat)->SetField(iField, nCount, panValues);
4800 : }
4801 :
4802 : /************************************************************************/
4803 : /* SetField() */
4804 : /************************************************************************/
4805 :
4806 : /**
4807 : * \fn OGRFeature::SetField( const char* pszFName, int nCount, const double *
4808 : * padfValues ) \brief Set field to list of doubles value.
4809 : *
4810 : * This method currently on has an effect of OFTIntegerList, OFTInteger64List,
4811 : * OFTRealList fields.
4812 : *
4813 : * @note This method has only an effect on the in-memory feature object. If
4814 : * this object comes from a layer and the modifications must be serialized back
4815 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4816 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4817 : *
4818 : * @param pszFName the name of the field to set.
4819 : * @param nCount the number of values in the list being assigned.
4820 : * @param padfValues the values to assign.
4821 : */
4822 :
4823 : /**
4824 : * \brief Set field to list of doubles value.
4825 : *
4826 : * This method currently on has an effect of OFTIntegerList, OFTInteger64List,
4827 : * OFTRealList fields.
4828 : *
4829 : * This method is the same as the C function OGR_F_SetFieldDoubleList().
4830 : *
4831 : * @note This method has only an effect on the in-memory feature object. If
4832 : * this object comes from a layer and the modifications must be serialized back
4833 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4834 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4835 : *
4836 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4837 : * @param nCount the number of values in the list being assigned.
4838 : * @param padfValues the values to assign.
4839 : */
4840 :
4841 21127 : void OGRFeature::SetField(int iField, int nCount, const double *padfValues)
4842 :
4843 : {
4844 21127 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
4845 :
4846 21127 : if (poFDefn == nullptr)
4847 0 : return;
4848 :
4849 21127 : OGRFieldType eType = poFDefn->GetType();
4850 21127 : if (eType == OFTRealList)
4851 : {
4852 : OGRField uField;
4853 :
4854 20870 : uField.RealList.nCount = nCount;
4855 20870 : uField.Set.nMarker2 = 0;
4856 20870 : uField.Set.nMarker3 = 0;
4857 20870 : uField.RealList.paList = const_cast<double *>(padfValues);
4858 :
4859 20870 : SetField(iField, &uField);
4860 : }
4861 257 : else if (eType == OFTIntegerList)
4862 : {
4863 366 : std::vector<int> anValues;
4864 183 : anValues.reserve(nCount);
4865 507 : for (int i = 0; i < nCount; i++)
4866 324 : anValues.push_back(static_cast<int>(padfValues[i]));
4867 :
4868 183 : if (nCount > 0)
4869 183 : SetField(iField, nCount, &anValues[0]);
4870 : }
4871 74 : else if (eType == OFTInteger64List)
4872 : {
4873 4 : std::vector<GIntBig> anValues;
4874 2 : anValues.reserve(nCount);
4875 5 : for (int i = 0; i < nCount; i++)
4876 3 : anValues.push_back(static_cast<GIntBig>(padfValues[i]));
4877 2 : if (nCount > 0)
4878 2 : SetField(iField, nCount, &anValues[0]);
4879 : }
4880 72 : else if ((eType == OFTInteger || eType == OFTInteger64 ||
4881 67 : eType == OFTReal) &&
4882 : nCount == 1)
4883 : {
4884 67 : SetField(iField, padfValues[0]);
4885 : }
4886 5 : else if (eType == OFTStringList)
4887 : {
4888 : char **papszValues = static_cast<char **>(
4889 1 : VSI_MALLOC_VERBOSE((nCount + 1) * sizeof(char *)));
4890 1 : if (papszValues == nullptr)
4891 0 : return;
4892 3 : for (int i = 0; i < nCount; i++)
4893 4 : papszValues[i] =
4894 2 : VSI_STRDUP_VERBOSE(CPLSPrintf("%.16g", padfValues[i]));
4895 1 : papszValues[nCount] = nullptr;
4896 1 : SetField(iField, papszValues);
4897 1 : CSLDestroy(papszValues);
4898 : }
4899 : }
4900 :
4901 : /************************************************************************/
4902 : /* OGR_F_SetFieldDoubleList() */
4903 : /************************************************************************/
4904 :
4905 : /**
4906 : * \brief Set field to list of doubles value.
4907 : *
4908 : * This function currently on has an effect of OFTIntegerList, OFTInteger64List,
4909 : * OFTRealList fields.
4910 : *
4911 : * This function is the same as the C++ method OGRFeature::SetField().
4912 : *
4913 : * @note This method has only an effect on the in-memory feature object. If
4914 : * this object comes from a layer and the modifications must be serialized back
4915 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4916 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4917 : *
4918 : * @param hFeat handle to the feature that owned the field.
4919 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4920 : * @param nCount the number of values in the list being assigned.
4921 : * @param padfValues the values to assign.
4922 : */
4923 :
4924 91 : void OGR_F_SetFieldDoubleList(OGRFeatureH hFeat, int iField, int nCount,
4925 : const double *padfValues)
4926 :
4927 : {
4928 91 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDoubleList");
4929 :
4930 91 : OGRFeature::FromHandle(hFeat)->SetField(iField, nCount, padfValues);
4931 : }
4932 :
4933 : /************************************************************************/
4934 : /* SetField() */
4935 : /************************************************************************/
4936 :
4937 : /**
4938 : * \fn OGRFeature::SetField( const char* pszFName, const char * const *
4939 : * papszValues ) \brief Set field to list of strings value.
4940 : *
4941 : * This method currently on has an effect of OFTStringList fields.
4942 : *
4943 : * @note This method has only an effect on the in-memory feature object. If
4944 : * this object comes from a layer and the modifications must be serialized back
4945 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4946 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4947 : *
4948 : * @param pszFName the name of the field to set.
4949 : * @param papszValues the values to assign. List of NUL-terminated string,
4950 : * ending with a NULL pointer.
4951 : */
4952 :
4953 : /**
4954 : * \brief Set field to list of strings value.
4955 : *
4956 : * This method currently on has an effect of OFTStringList fields.
4957 : *
4958 : * This method is the same as the C function OGR_F_SetFieldStringList().
4959 : *
4960 : * @note This method has only an effect on the in-memory feature object. If
4961 : * this object comes from a layer and the modifications must be serialized back
4962 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
4963 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
4964 : *
4965 : * @param iField the field to set, from 0 to GetFieldCount()-1.
4966 : * @param papszValues the values to assign. List of NUL-terminated string,
4967 : * ending with a NULL pointer.
4968 : */
4969 :
4970 37805 : void OGRFeature::SetField(int iField, const char *const *papszValues)
4971 :
4972 : {
4973 37805 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
4974 :
4975 37805 : if (poFDefn == nullptr)
4976 0 : return;
4977 :
4978 37805 : OGRFieldType eType = poFDefn->GetType();
4979 37805 : if (eType == OFTStringList)
4980 : {
4981 24569 : if (!IsFieldSetAndNotNullUnsafe(iField) ||
4982 5629 : papszValues != pauFields[iField].StringList.paList)
4983 : {
4984 : OGRField uField;
4985 :
4986 18938 : uField.StringList.nCount = CSLCount(papszValues);
4987 18938 : uField.Set.nMarker2 = 0;
4988 18938 : uField.Set.nMarker3 = 0;
4989 18938 : uField.StringList.paList = const_cast<char **>(papszValues);
4990 :
4991 18938 : SetField(iField, &uField);
4992 : }
4993 : }
4994 18865 : else if (eType == OFTIntegerList)
4995 : {
4996 9845 : const int nValues = CSLCount(papszValues);
4997 : int *panValues =
4998 9845 : static_cast<int *>(VSI_MALLOC_VERBOSE(nValues * sizeof(int)));
4999 9845 : if (panValues == nullptr)
5000 0 : return;
5001 28447 : for (int i = 0; i < nValues; i++)
5002 : {
5003 : // As allowed by C standard, some systems like MSVC do not
5004 : // reset errno.
5005 18602 : errno = 0;
5006 :
5007 18602 : int nVal = atoi(papszValues[i]);
5008 18602 : if (errno == ERANGE)
5009 : {
5010 0 : CPLError(
5011 : CE_Warning, CPLE_AppDefined,
5012 : "Field %s.%s: 32 bit integer overflow when converting %s",
5013 0 : poDefn->GetName(), poFDefn->GetNameRef(), papszValues[i]);
5014 0 : if (papszValues[i][0] == '-')
5015 0 : nVal = INT_MIN;
5016 : else
5017 0 : nVal = INT_MAX;
5018 : }
5019 18602 : panValues[i] = nVal;
5020 : }
5021 9845 : SetField(iField, nValues, panValues);
5022 9845 : CPLFree(panValues);
5023 : }
5024 9020 : else if (eType == OFTInteger64List)
5025 : {
5026 3377 : const int nValues = CSLCount(papszValues);
5027 : GIntBig *panValues = static_cast<GIntBig *>(
5028 3377 : VSI_MALLOC_VERBOSE(nValues * sizeof(GIntBig)));
5029 3377 : if (panValues == nullptr)
5030 0 : return;
5031 10073 : for (int i = 0; i < nValues; i++)
5032 : {
5033 6696 : panValues[i] = CPLAtoGIntBigEx(papszValues[i], TRUE, nullptr);
5034 : }
5035 3377 : SetField(iField, nValues, panValues);
5036 3377 : CPLFree(panValues);
5037 : }
5038 5643 : else if (eType == OFTRealList)
5039 : {
5040 5643 : const int nValues = CSLCount(papszValues);
5041 : double *padfValues =
5042 5643 : static_cast<double *>(VSI_MALLOC_VERBOSE(nValues * sizeof(double)));
5043 5643 : if (padfValues == nullptr)
5044 0 : return;
5045 15738 : for (int i = 0; i < nValues; i++)
5046 : {
5047 10095 : padfValues[i] = CPLAtof(papszValues[i]);
5048 : }
5049 5643 : SetField(iField, nValues, padfValues);
5050 5643 : CPLFree(padfValues);
5051 : }
5052 : }
5053 :
5054 : /************************************************************************/
5055 : /* OGR_F_SetFieldStringList() */
5056 : /************************************************************************/
5057 :
5058 : /**
5059 : * \brief Set field to list of strings value.
5060 : *
5061 : * This function currently on has an effect of OFTStringList fields.
5062 : *
5063 : * This function is the same as the C++ method OGRFeature::SetField().
5064 : *
5065 : * @note This method has only an effect on the in-memory feature object. If
5066 : * this object comes from a layer and the modifications must be serialized back
5067 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5068 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5069 : *
5070 : * @param hFeat handle to the feature that owned the field.
5071 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5072 : * @param papszValues the values to assign. List of NUL-terminated string,
5073 : * ending with a NULL pointer.
5074 : */
5075 :
5076 43 : void OGR_F_SetFieldStringList(OGRFeatureH hFeat, int iField,
5077 : CSLConstList papszValues)
5078 :
5079 : {
5080 43 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldStringList");
5081 :
5082 43 : OGRFeature::FromHandle(hFeat)->SetField(iField, papszValues);
5083 : }
5084 :
5085 : /************************************************************************/
5086 : /* SetField() */
5087 : /************************************************************************/
5088 :
5089 : /**
5090 : * \brief Set field to binary data.
5091 : *
5092 : * This method currently on has an effect of OFTBinary fields.
5093 : *
5094 : * This method is the same as the C function OGR_F_SetFieldBinary().
5095 : *
5096 : * @note This method has only an effect on the in-memory feature object. If
5097 : * this object comes from a layer and the modifications must be serialized back
5098 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5099 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5100 : *
5101 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5102 : * @param nBytes bytes of data being set.
5103 : * @param pabyData the raw data being applied.
5104 : */
5105 :
5106 18017 : void OGRFeature::SetField(int iField, int nBytes, const void *pabyData)
5107 :
5108 : {
5109 18017 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
5110 :
5111 18017 : if (poFDefn == nullptr)
5112 0 : return;
5113 :
5114 18017 : OGRFieldType eType = poFDefn->GetType();
5115 18017 : if (eType == OFTBinary)
5116 : {
5117 : OGRField uField;
5118 :
5119 18014 : uField.Binary.nCount = nBytes;
5120 18014 : uField.Set.nMarker2 = 0;
5121 18014 : uField.Set.nMarker3 = 0;
5122 18014 : uField.Binary.paData =
5123 : const_cast<GByte *>(static_cast<const GByte *>(pabyData));
5124 :
5125 18014 : SetField(iField, &uField);
5126 : }
5127 3 : else if (eType == OFTString || eType == OFTStringList)
5128 : {
5129 3 : char *pszStr = static_cast<char *>(VSI_MALLOC_VERBOSE(nBytes + 1));
5130 3 : if (pszStr == nullptr)
5131 0 : return;
5132 3 : if (nBytes > 0)
5133 3 : memcpy(pszStr, pabyData, nBytes);
5134 3 : pszStr[nBytes] = 0;
5135 3 : SetField(iField, pszStr);
5136 3 : CPLFree(pszStr);
5137 : }
5138 : }
5139 :
5140 : /************************************************************************/
5141 : /* OGR_F_SetFieldBinary() */
5142 : /************************************************************************/
5143 :
5144 : /**
5145 : * \brief Set field to binary data.
5146 : *
5147 : * This function currently on has an effect of OFTBinary fields.
5148 : *
5149 : * This function is the same as the C++ method OGRFeature::SetField().
5150 : *
5151 : * @note This method has only an effect on the in-memory feature object. If
5152 : * this object comes from a layer and the modifications must be serialized back
5153 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5154 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5155 : *
5156 : * @param hFeat handle to the feature that owned the field.
5157 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5158 : * @param nBytes the number of bytes in pabyData array.
5159 : * @param pabyData the data to apply.
5160 : */
5161 :
5162 524 : void OGR_F_SetFieldBinary(OGRFeatureH hFeat, int iField, int nBytes,
5163 : const void *pabyData)
5164 :
5165 : {
5166 524 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldBinary");
5167 :
5168 524 : OGRFeature::FromHandle(hFeat)->SetField(iField, nBytes, pabyData);
5169 : }
5170 :
5171 : /************************************************************************/
5172 : /* SetField() */
5173 : /************************************************************************/
5174 :
5175 : /**
5176 : * \fn OGRFeature::SetField( const char* pszFName, int nYear, int nMonth,
5177 : * int nDay, int nHour, int nMinute, float fSecond,
5178 : * int nTZFlag )
5179 : * \brief Set field to date.
5180 : *
5181 : * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
5182 : * fields.
5183 : *
5184 : * @note This method has only an effect on the in-memory feature object. If
5185 : * this object comes from a layer and the modifications must be serialized back
5186 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5187 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5188 : *
5189 : * @param pszFName the name of the field to set.
5190 : * @param nYear (including century)
5191 : * @param nMonth (1-12)
5192 : * @param nDay (1-31)
5193 : * @param nHour (0-23)
5194 : * @param nMinute (0-59)
5195 : * @param fSecond (0-59, with millisecond accuracy)
5196 : * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
5197 : */
5198 :
5199 : /**
5200 : * \brief Set field to date.
5201 : *
5202 : * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
5203 : * fields.
5204 : *
5205 : * This method is the same as the C function OGR_F_SetFieldDateTime().
5206 : *
5207 : * @note This method has only an effect on the in-memory feature object. If
5208 : * this object comes from a layer and the modifications must be serialized back
5209 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5210 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5211 : *
5212 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5213 : * @param nYear (including century)
5214 : * @param nMonth (1-12)
5215 : * @param nDay (1-31)
5216 : * @param nHour (0-23)
5217 : * @param nMinute (0-59)
5218 : * @param fSecond (0-59, with millisecond accuracy)
5219 : * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
5220 : */
5221 :
5222 10705 : void OGRFeature::SetField(int iField, int nYear, int nMonth, int nDay,
5223 : int nHour, int nMinute, float fSecond, int nTZFlag)
5224 :
5225 : {
5226 10705 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
5227 :
5228 10705 : if (poFDefn == nullptr)
5229 0 : return;
5230 :
5231 10705 : OGRFieldType eType = poFDefn->GetType();
5232 10705 : if (eType == OFTDate || eType == OFTTime || eType == OFTDateTime)
5233 : {
5234 10697 : if (static_cast<GInt16>(nYear) != nYear)
5235 : {
5236 0 : CPLError(CE_Failure, CPLE_NotSupported,
5237 : "Years < -32768 or > 32767 are not supported");
5238 0 : return;
5239 : }
5240 :
5241 10697 : pauFields[iField].Date.Year = static_cast<GInt16>(nYear);
5242 10697 : pauFields[iField].Date.Month = static_cast<GByte>(nMonth);
5243 10697 : pauFields[iField].Date.Day = static_cast<GByte>(nDay);
5244 10697 : pauFields[iField].Date.Hour = static_cast<GByte>(nHour);
5245 10697 : pauFields[iField].Date.Minute = static_cast<GByte>(nMinute);
5246 10697 : pauFields[iField].Date.Second = fSecond;
5247 10697 : pauFields[iField].Date.TZFlag = static_cast<GByte>(nTZFlag);
5248 : }
5249 8 : else if (eType == OFTString || eType == OFTStringList)
5250 : {
5251 : // "YYYY/MM/DD HH:MM:SS.sss+ZZ"
5252 8 : constexpr size_t MAX_SIZE = 26 + 1;
5253 8 : char szTempBuffer[MAX_SIZE] = {};
5254 8 : OGRFeatureFormatDateTimeBuffer(szTempBuffer, MAX_SIZE, nYear, nMonth,
5255 : nDay, nHour, nMinute, fSecond, nTZFlag);
5256 8 : SetField(iField, szTempBuffer);
5257 : }
5258 : }
5259 :
5260 : /************************************************************************/
5261 : /* OGR_F_SetFieldDateTime() */
5262 : /************************************************************************/
5263 :
5264 : /**
5265 : * \brief Set field to datetime.
5266 : *
5267 : * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
5268 : * fields.
5269 : *
5270 : * @note This method has only an effect on the in-memory feature object. If
5271 : * this object comes from a layer and the modifications must be serialized back
5272 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5273 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5274 : *
5275 : * @param hFeat handle to the feature that owned the field.
5276 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5277 : * @param nYear (including century)
5278 : * @param nMonth (1-12)
5279 : * @param nDay (1-31)
5280 : * @param nHour (0-23)
5281 : * @param nMinute (0-59)
5282 : * @param nSecond (0-59)
5283 : * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
5284 : *
5285 : * @see Use OGR_F_SetFieldDateTimeEx() for second with millisecond accuracy.
5286 : */
5287 :
5288 0 : void OGR_F_SetFieldDateTime(OGRFeatureH hFeat, int iField, int nYear,
5289 : int nMonth, int nDay, int nHour, int nMinute,
5290 : int nSecond, int nTZFlag)
5291 :
5292 : {
5293 0 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDateTime");
5294 :
5295 0 : OGRFeature::FromHandle(hFeat)->SetField(
5296 : iField, nYear, nMonth, nDay, nHour, nMinute,
5297 : static_cast<float>(nSecond), nTZFlag);
5298 : }
5299 :
5300 : /************************************************************************/
5301 : /* OGR_F_SetFieldDateTimeEx() */
5302 : /************************************************************************/
5303 :
5304 : /**
5305 : * \brief Set field to datetime.
5306 : *
5307 : * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
5308 : * fields.
5309 : *
5310 : * @note This method has only an effect on the in-memory feature object. If
5311 : * this object comes from a layer and the modifications must be serialized back
5312 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5313 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5314 : *
5315 : * @param hFeat handle to the feature that owned the field.
5316 : * @param iField the field to set, from 0 to GetFieldCount()-1.
5317 : * @param nYear (including century)
5318 : * @param nMonth (1-12)
5319 : * @param nDay (1-31)
5320 : * @param nHour (0-23)
5321 : * @param nMinute (0-59)
5322 : * @param fSecond (0-59, with millisecond accuracy)
5323 : * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
5324 : *
5325 : */
5326 :
5327 45 : void OGR_F_SetFieldDateTimeEx(OGRFeatureH hFeat, int iField, int nYear,
5328 : int nMonth, int nDay, int nHour, int nMinute,
5329 : float fSecond, int nTZFlag)
5330 :
5331 : {
5332 45 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldDateTimeEx");
5333 :
5334 45 : OGRFeature::FromHandle(hFeat)->SetField(iField, nYear, nMonth, nDay, nHour,
5335 : nMinute, fSecond, nTZFlag);
5336 : }
5337 :
5338 : /************************************************************************/
5339 : /* SetField() */
5340 : /************************************************************************/
5341 :
5342 : /**
5343 : * \fn OGRFeature::SetField( const char* pszFName, const OGRField * puValue )
5344 : * \brief Set field.
5345 : *
5346 : * The passed value OGRField must be of exactly the same type as the
5347 : * target field, or an application crash may occur. The passed value
5348 : * is copied, and will not be affected. It remains the responsibility of
5349 : * the caller.
5350 : *
5351 : * @note This method has only an effect on the in-memory feature object. If
5352 : * this object comes from a layer and the modifications must be serialized back
5353 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5354 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5355 : *
5356 : * @param pszFName the name of the field to set.
5357 : * @param puValue the value to assign.
5358 : */
5359 :
5360 : /**
5361 : * \brief Set field.
5362 : *
5363 : * The passed value OGRField must be of exactly the same type as the
5364 : * target field, or an application crash may occur. The passed value
5365 : * is copied, and will not be affected. It remains the responsibility of
5366 : * the caller.
5367 : *
5368 : * This method is the same as the C function OGR_F_SetFieldRaw().
5369 : *
5370 : * @note This method has only an effect on the in-memory feature object. If
5371 : * this object comes from a layer and the modifications must be serialized back
5372 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5373 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5374 : *
5375 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
5376 : * @param puValue the value to assign.
5377 : */
5378 :
5379 390919 : void OGRFeature::SetField(int iField, const OGRField *puValue)
5380 :
5381 : {
5382 390919 : SetFieldInternal(iField, puValue);
5383 390919 : }
5384 :
5385 4623370 : bool OGRFeature::SetFieldInternal(int iField, const OGRField *puValue)
5386 :
5387 : {
5388 4623370 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
5389 4623370 : if (iField < 0 || poFDefn == nullptr)
5390 0 : return false;
5391 :
5392 4623370 : if (poFDefn->GetType() == OFTInteger)
5393 : {
5394 1315440 : pauFields[iField] = *puValue;
5395 : }
5396 3307930 : else if (poFDefn->GetType() == OFTInteger64)
5397 : {
5398 25869 : pauFields[iField] = *puValue;
5399 : }
5400 3282060 : else if (poFDefn->GetType() == OFTReal)
5401 : {
5402 77715 : pauFields[iField] = *puValue;
5403 : }
5404 3204350 : else if (poFDefn->GetType() == OFTString)
5405 : {
5406 2910890 : if (IsFieldSetAndNotNullUnsafe(iField))
5407 28 : CPLFree(pauFields[iField].String);
5408 :
5409 2910890 : if (puValue->String == nullptr)
5410 0 : pauFields[iField].String = nullptr;
5411 2910890 : else if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
5412 1217950 : pauFields[iField] = *puValue;
5413 : else
5414 : {
5415 1692940 : pauFields[iField].String = VSI_STRDUP_VERBOSE(puValue->String);
5416 1692940 : if (pauFields[iField].String == nullptr)
5417 : {
5418 0 : OGR_RawField_SetUnset(&pauFields[iField]);
5419 0 : return false;
5420 : }
5421 : }
5422 : }
5423 542422 : else if (poFDefn->GetType() == OFTDate || poFDefn->GetType() == OFTTime ||
5424 248960 : poFDefn->GetType() == OFTDateTime)
5425 : {
5426 105660 : memcpy(pauFields + iField, puValue, sizeof(OGRField));
5427 : }
5428 187802 : else if (poFDefn->GetType() == OFTIntegerList)
5429 : {
5430 43845 : const int nCount = puValue->IntegerList.nCount;
5431 :
5432 43845 : if (IsFieldSetAndNotNullUnsafe(iField))
5433 3343 : CPLFree(pauFields[iField].IntegerList.paList);
5434 :
5435 43845 : if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
5436 : {
5437 350 : pauFields[iField] = *puValue;
5438 : }
5439 : else
5440 : {
5441 86990 : pauFields[iField].IntegerList.paList =
5442 43495 : static_cast<int *>(VSI_MALLOC_VERBOSE(sizeof(int) * nCount));
5443 43495 : if (pauFields[iField].IntegerList.paList == nullptr)
5444 : {
5445 0 : OGR_RawField_SetUnset(&pauFields[iField]);
5446 0 : return false;
5447 : }
5448 43495 : if (nCount > 0)
5449 : {
5450 40487 : memcpy(pauFields[iField].IntegerList.paList,
5451 40487 : puValue->IntegerList.paList, sizeof(int) * nCount);
5452 : }
5453 43495 : pauFields[iField].IntegerList.nCount = nCount;
5454 : }
5455 : }
5456 143957 : else if (poFDefn->GetType() == OFTInteger64List)
5457 : {
5458 23326 : const int nCount = puValue->Integer64List.nCount;
5459 :
5460 23326 : if (IsFieldSetAndNotNullUnsafe(iField))
5461 1168 : CPLFree(pauFields[iField].Integer64List.paList);
5462 :
5463 23326 : if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
5464 : {
5465 111 : pauFields[iField] = *puValue;
5466 : }
5467 : else
5468 : {
5469 46430 : pauFields[iField].Integer64List.paList = static_cast<GIntBig *>(
5470 23215 : VSI_MALLOC_VERBOSE(sizeof(GIntBig) * nCount));
5471 23215 : if (pauFields[iField].Integer64List.paList == nullptr)
5472 : {
5473 0 : OGR_RawField_SetUnset(&pauFields[iField]);
5474 0 : return false;
5475 : }
5476 23215 : if (nCount > 0)
5477 : {
5478 22252 : memcpy(pauFields[iField].Integer64List.paList,
5479 22252 : puValue->Integer64List.paList, sizeof(GIntBig) * nCount);
5480 : }
5481 23215 : pauFields[iField].Integer64List.nCount = nCount;
5482 : }
5483 : }
5484 120631 : else if (poFDefn->GetType() == OFTRealList)
5485 : {
5486 32047 : const int nCount = puValue->RealList.nCount;
5487 :
5488 32047 : if (IsFieldSetAndNotNullUnsafe(iField))
5489 2343 : CPLFree(pauFields[iField].RealList.paList);
5490 :
5491 32047 : if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
5492 : {
5493 10412 : pauFields[iField] = *puValue;
5494 : }
5495 : else
5496 : {
5497 43270 : pauFields[iField].RealList.paList = static_cast<double *>(
5498 21635 : VSI_MALLOC_VERBOSE(sizeof(double) * nCount));
5499 21635 : if (pauFields[iField].RealList.paList == nullptr)
5500 : {
5501 0 : OGR_RawField_SetUnset(&pauFields[iField]);
5502 0 : return false;
5503 : }
5504 21635 : if (nCount > 0)
5505 : {
5506 20012 : memcpy(pauFields[iField].RealList.paList,
5507 20012 : puValue->RealList.paList, sizeof(double) * nCount);
5508 : }
5509 21635 : pauFields[iField].RealList.nCount = nCount;
5510 : }
5511 : }
5512 88584 : else if (poFDefn->GetType() == OFTStringList)
5513 : {
5514 29676 : if (IsFieldSetAndNotNullUnsafe(iField))
5515 5627 : CSLDestroy(pauFields[iField].StringList.paList);
5516 :
5517 29676 : if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
5518 : {
5519 272 : pauFields[iField] = *puValue;
5520 : }
5521 : else
5522 : {
5523 29404 : char **papszNewList = nullptr;
5524 29404 : for (char **papszIter = puValue->StringList.paList;
5525 84316 : papszIter != nullptr && *papszIter != nullptr; ++papszIter)
5526 : {
5527 : char **papszNewList2 =
5528 54912 : CSLAddStringMayFail(papszNewList, *papszIter);
5529 54912 : if (papszNewList2 == nullptr)
5530 : {
5531 0 : CSLDestroy(papszNewList);
5532 0 : OGR_RawField_SetUnset(&pauFields[iField]);
5533 0 : return false;
5534 : }
5535 54912 : papszNewList = papszNewList2;
5536 : }
5537 29404 : pauFields[iField].StringList.paList = papszNewList;
5538 29404 : pauFields[iField].StringList.nCount = puValue->StringList.nCount;
5539 29404 : CPLAssert(CSLCount(puValue->StringList.paList) ==
5540 : puValue->StringList.nCount);
5541 : }
5542 : }
5543 58908 : else if (poFDefn->GetType() == OFTBinary)
5544 : {
5545 58908 : if (IsFieldSetAndNotNullUnsafe(iField))
5546 103 : CPLFree(pauFields[iField].Binary.paData);
5547 :
5548 58908 : if (OGR_RawField_IsUnset(puValue) || OGR_RawField_IsNull(puValue))
5549 : {
5550 105 : pauFields[iField] = *puValue;
5551 : }
5552 : else
5553 : {
5554 117606 : pauFields[iField].Binary.paData = static_cast<GByte *>(
5555 58803 : VSI_MALLOC_VERBOSE(puValue->Binary.nCount));
5556 58803 : if (pauFields[iField].Binary.paData == nullptr)
5557 : {
5558 0 : OGR_RawField_SetUnset(&pauFields[iField]);
5559 0 : return false;
5560 : }
5561 58803 : if (puValue->Binary.nCount > 0)
5562 : {
5563 58760 : memcpy(pauFields[iField].Binary.paData, puValue->Binary.paData,
5564 58760 : puValue->Binary.nCount);
5565 : }
5566 58803 : pauFields[iField].Binary.nCount = puValue->Binary.nCount;
5567 : }
5568 : }
5569 : else
5570 : {
5571 : // Do nothing for other field types.
5572 : }
5573 4623370 : return true;
5574 : }
5575 :
5576 : /************************************************************************/
5577 : /* OGR_F_SetFieldRaw() */
5578 : /************************************************************************/
5579 :
5580 : /**
5581 : * \brief Set field.
5582 : *
5583 : * The passed value OGRField must be of exactly the same type as the
5584 : * target field, or an application crash may occur. The passed value
5585 : * is copied, and will not be affected. It remains the responsibility of
5586 : * the caller.
5587 : *
5588 : * This function is the same as the C++ method OGRFeature::SetField().
5589 : *
5590 : * @note This method has only an effect on the in-memory feature object. If
5591 : * this object comes from a layer and the modifications must be serialized back
5592 : * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
5593 : * a new feature, OGR_L_CreateFeature() must be used afterwards.
5594 : *
5595 : * @param hFeat handle to the feature that owned the field.
5596 : * @param iField the field to fetch, from 0 to GetFieldCount()-1.
5597 : * @param psValue handle on the value to assign.
5598 : */
5599 :
5600 0 : void OGR_F_SetFieldRaw(OGRFeatureH hFeat, int iField, const OGRField *psValue)
5601 :
5602 : {
5603 0 : VALIDATE_POINTER0(hFeat, "OGR_F_SetFieldRaw");
5604 :
5605 0 : OGRFeature::FromHandle(hFeat)->SetField(iField, psValue);
5606 : }
5607 :
5608 : /************************************************************************/
5609 : /* DumpReadable() */
5610 : /************************************************************************/
5611 :
5612 : /**
5613 : * \brief Dump this feature in a human readable form.
5614 : *
5615 : * This dumps the attributes, and geometry; however, it doesn't definition
5616 : * information (other than field types and names), nor does it report the
5617 : * geometry spatial reference system.
5618 : *
5619 : * A few options can be defined to change the default dump :
5620 : * <ul>
5621 : * <li>DISPLAY_FIELDS=NO : to hide the dump of the attributes</li>
5622 : * <li>DISPLAY_STYLE=NO : to hide the dump of the style string</li>
5623 : * <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
5624 : * <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
5625 : * </ul>
5626 : *
5627 : * This method is the same as the C function OGR_F_DumpReadable().
5628 : *
5629 : * @param fpOut the stream to write to, such as stdout. If NULL stdout will
5630 : * be used.
5631 : * @param papszOptions NULL terminated list of options (may be NULL)
5632 : */
5633 :
5634 121 : void OGRFeature::DumpReadable(FILE *fpOut, CSLConstList papszOptions) const
5635 :
5636 : {
5637 121 : if (fpOut == nullptr)
5638 121 : fpOut = stdout;
5639 :
5640 242 : const auto osStr = DumpReadableAsString(papszOptions);
5641 121 : fprintf(fpOut, "%s", osStr.c_str());
5642 121 : }
5643 :
5644 : /************************************************************************/
5645 : /* DumpReadableAsString() */
5646 : /************************************************************************/
5647 :
5648 : /**
5649 : * \brief Dump this feature in a human readable form.
5650 : *
5651 : * This dumps the attributes, and geometry; however, it doesn't definition
5652 : * information (other than field types and names), nor does it report the
5653 : * geometry spatial reference system.
5654 : *
5655 : * A few options can be defined to change the default dump :
5656 : * <ul>
5657 : * <li>DISPLAY_FIELDS=NO : to hide the dump of the attributes</li>
5658 : * <li>DISPLAY_STYLE=NO : to hide the dump of the style string</li>
5659 : * <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
5660 : * <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
5661 : * </ul>
5662 : *
5663 : * @param papszOptions NULL terminated list of options (may be NULL)
5664 : * @return a string with the feature representation.
5665 : * @since GDAL 3.7
5666 : */
5667 :
5668 827 : std::string OGRFeature::DumpReadableAsString(CSLConstList papszOptions) const
5669 : {
5670 827 : std::string osRet;
5671 :
5672 1654 : osRet += CPLOPrintf("OGRFeature(%s):" CPL_FRMT_GIB "\n", poDefn->GetName(),
5673 827 : GetFID());
5674 :
5675 : const char *pszDisplayFields =
5676 827 : CSLFetchNameValue(papszOptions, "DISPLAY_FIELDS");
5677 827 : if (pszDisplayFields == nullptr || CPLTestBool(pszDisplayFields))
5678 : {
5679 816 : const int nFieldCount = GetFieldCount();
5680 8168 : for (int iField = 0; iField < nFieldCount; iField++)
5681 : {
5682 7352 : if (!IsFieldSet(iField))
5683 2560 : continue;
5684 4792 : const OGRFieldDefn *poFDefn = poDefn->GetFieldDefnUnsafe(iField);
5685 :
5686 : const char *pszType =
5687 4792 : (poFDefn->GetSubType() != OFSTNone)
5688 4792 : ? CPLSPrintf(
5689 : "%s(%s)",
5690 : poFDefn->GetFieldTypeName(poFDefn->GetType()),
5691 : poFDefn->GetFieldSubTypeName(poFDefn->GetSubType()))
5692 4354 : : poFDefn->GetFieldTypeName(poFDefn->GetType());
5693 :
5694 4792 : osRet += CPLOPrintf(" %s (%s) = ", poFDefn->GetNameRef(), pszType);
5695 :
5696 4792 : if (IsFieldNull(iField))
5697 45 : osRet += "(null)\n";
5698 : else
5699 4747 : osRet += CPLOPrintf("%s\n", GetFieldAsString(iField));
5700 : }
5701 : }
5702 :
5703 827 : if (GetStyleString() != nullptr)
5704 : {
5705 : const char *pszDisplayStyle =
5706 4 : CSLFetchNameValue(papszOptions, "DISPLAY_STYLE");
5707 4 : if (pszDisplayStyle == nullptr || CPLTestBool(pszDisplayStyle))
5708 : {
5709 4 : osRet += CPLOPrintf(" Style = %s\n", GetStyleString());
5710 : }
5711 : }
5712 :
5713 827 : const int nGeomFieldCount = GetGeomFieldCount();
5714 827 : if (nGeomFieldCount > 0)
5715 : {
5716 : const char *pszDisplayGeometry =
5717 311 : CSLFetchNameValue(papszOptions, "DISPLAY_GEOMETRY");
5718 311 : if (!(pszDisplayGeometry != nullptr && EQUAL(pszDisplayGeometry, "NO")))
5719 : {
5720 606 : for (int iField = 0; iField < nGeomFieldCount; iField++)
5721 : {
5722 : const OGRGeomFieldDefn *poFDefn =
5723 306 : poDefn->GetGeomFieldDefn(iField);
5724 :
5725 306 : if (papoGeometries[iField] != nullptr)
5726 : {
5727 303 : CPLStringList aosGeomOptions(papszOptions);
5728 :
5729 303 : const auto &oCoordPrec = poFDefn->GetCoordinatePrecision();
5730 :
5731 303 : if (oCoordPrec.dfXYResolution !=
5732 : OGRGeomCoordinatePrecision::UNKNOWN)
5733 : {
5734 : aosGeomOptions.SetNameValue(
5735 : "XY_COORD_PRECISION",
5736 : CPLSPrintf("%d",
5737 : OGRGeomCoordinatePrecision::
5738 : ResolutionToPrecision(
5739 1 : oCoordPrec.dfXYResolution)));
5740 : }
5741 303 : if (oCoordPrec.dfZResolution !=
5742 : OGRGeomCoordinatePrecision::UNKNOWN)
5743 : {
5744 : aosGeomOptions.SetNameValue(
5745 : "Z_COORD_PRECISION",
5746 : CPLSPrintf("%d",
5747 : OGRGeomCoordinatePrecision::
5748 : ResolutionToPrecision(
5749 1 : oCoordPrec.dfZResolution)));
5750 : }
5751 :
5752 303 : osRet += " ";
5753 355 : if (strlen(poFDefn->GetNameRef()) > 0 &&
5754 52 : GetGeomFieldCount() > 1)
5755 12 : osRet += CPLOPrintf("%s = ", poFDefn->GetNameRef());
5756 606 : osRet += papoGeometries[iField]->dumpReadable(
5757 606 : nullptr, aosGeomOptions.List());
5758 : }
5759 : }
5760 : }
5761 : }
5762 :
5763 827 : osRet += "\n";
5764 827 : return osRet;
5765 : }
5766 :
5767 : /************************************************************************/
5768 : /* OGR_F_DumpReadable() */
5769 : /************************************************************************/
5770 :
5771 : /**
5772 : * \brief Dump this feature in a human readable form.
5773 : *
5774 : * This dumps the attributes, and geometry; however, it doesn't definition
5775 : * information (other than field types and names), nor does it report the
5776 : * geometry spatial reference system.
5777 : *
5778 : * This function is the same as the C++ method OGRFeature::DumpReadable().
5779 : *
5780 : * @param hFeat handle to the feature to dump.
5781 : * @param fpOut the stream to write to, such as strout.
5782 : */
5783 :
5784 31 : void OGR_F_DumpReadable(OGRFeatureH hFeat, FILE *fpOut)
5785 :
5786 : {
5787 31 : VALIDATE_POINTER0(hFeat, "OGR_F_DumpReadable");
5788 :
5789 31 : OGRFeature::FromHandle(hFeat)->DumpReadable(fpOut);
5790 : }
5791 :
5792 : /************************************************************************/
5793 : /* OGR_F_DumpReadableAsString() */
5794 : /************************************************************************/
5795 :
5796 : /**
5797 : * \brief Dump this feature in a human readable form.
5798 : *
5799 : * This dumps the attributes, and geometry; however, it doesn't include
5800 : * definition information (other than field types and names), nor does
5801 : * it report the geometry spatial reference system.
5802 : *
5803 : * A few options can be defined to change the default dump :
5804 : * <ul>
5805 : * <li>DISPLAY_FIELDS=NO : to hide the dump of the attributes</li>
5806 : * <li>DISPLAY_STYLE=NO : to hide the dump of the style string</li>
5807 : * <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
5808 : * <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
5809 : * </ul>
5810 : *
5811 : * @param hFeat handle to the feature to dump.
5812 : * @param papszOptions NULL terminated list of options (may be NULL)
5813 : * @return a string with the feature representation (to be freed with CPLFree())
5814 : * @since GDAL 3.8
5815 : */
5816 :
5817 96 : char *OGR_F_DumpReadableAsString(OGRFeatureH hFeat, CSLConstList papszOptions)
5818 : {
5819 96 : VALIDATE_POINTER1(hFeat, "OGR_F_DumpReadableAsString", nullptr);
5820 :
5821 96 : return CPLStrdup(OGRFeature::FromHandle(hFeat)
5822 192 : ->DumpReadableAsString(papszOptions)
5823 96 : .c_str());
5824 : }
5825 :
5826 : /************************************************************************/
5827 : /* GetFID() */
5828 : /************************************************************************/
5829 :
5830 : /**
5831 : * \fn GIntBig OGRFeature::GetFID() const;
5832 : *
5833 : * \brief Get feature identifier.
5834 : *
5835 : * This method is the same as the C function OGR_F_GetFID().
5836 : *
5837 : * @return feature id or OGRNullFID if none has been assigned.
5838 : */
5839 :
5840 : /************************************************************************/
5841 : /* OGR_F_GetFID() */
5842 : /************************************************************************/
5843 :
5844 : /**
5845 : * \brief Get feature identifier.
5846 : *
5847 : * This function is the same as the C++ method OGRFeature::GetFID().
5848 : *
5849 : * @param hFeat handle to the feature from which to get the feature
5850 : * identifier.
5851 : * @return feature id or OGRNullFID if none has been assigned.
5852 : */
5853 :
5854 5475 : GIntBig OGR_F_GetFID(OGRFeatureH hFeat)
5855 :
5856 : {
5857 5475 : VALIDATE_POINTER1(hFeat, "OGR_F_GetFID", 0);
5858 :
5859 5475 : return OGRFeature::FromHandle(hFeat)->GetFID();
5860 : }
5861 :
5862 : /************************************************************************/
5863 : /* SetFID() */
5864 : /************************************************************************/
5865 :
5866 : /**
5867 : * \brief Set the feature identifier.
5868 : *
5869 : * For specific types of features this operation may fail on illegal
5870 : * features ids. Generally it always succeeds. Feature ids should be
5871 : * greater than or equal to zero, with the exception of OGRNullFID (-1)
5872 : * indicating that the feature id is unknown.
5873 : *
5874 : * This method is the same as the C function OGR_F_SetFID().
5875 : *
5876 : * @param nFIDIn the new feature identifier value to assign.
5877 : *
5878 : * @return On success OGRERR_NONE, or on failure some other value.
5879 : */
5880 :
5881 3041630 : OGRErr OGRFeature::SetFID(GIntBig nFIDIn)
5882 :
5883 : {
5884 3041630 : nFID = nFIDIn;
5885 :
5886 3041630 : return OGRERR_NONE;
5887 : }
5888 :
5889 : /************************************************************************/
5890 : /* OGR_F_SetFID() */
5891 : /************************************************************************/
5892 :
5893 : /**
5894 : * \brief Set the feature identifier.
5895 : *
5896 : * For specific types of features this operation may fail on illegal
5897 : * features ids. Generally it always succeeds. Feature ids should be
5898 : * greater than or equal to zero, with the exception of OGRNullFID (-1)
5899 : * indicating that the feature id is unknown.
5900 : *
5901 : * This function is the same as the C++ method OGRFeature::SetFID().
5902 : *
5903 : * @param hFeat handle to the feature to set the feature id to.
5904 : * @param nFID the new feature identifier value to assign.
5905 : *
5906 : * @return On success OGRERR_NONE, or on failure some other value.
5907 : */
5908 :
5909 170868 : OGRErr OGR_F_SetFID(OGRFeatureH hFeat, GIntBig nFID)
5910 :
5911 : {
5912 170868 : VALIDATE_POINTER1(hFeat, "OGR_F_SetFID", OGRERR_FAILURE);
5913 :
5914 170868 : return OGRFeature::FromHandle(hFeat)->SetFID(nFID);
5915 : }
5916 :
5917 : /************************************************************************/
5918 : /* Equal() */
5919 : /************************************************************************/
5920 :
5921 : /**
5922 : * \brief Test if two features are the same.
5923 : *
5924 : * Two features are considered equal if the share them (pointer equality)
5925 : * same OGRFeatureDefn, have the same field values, and the same geometry
5926 : * (as tested by OGRGeometry::Equal()) as well as the same feature id.
5927 : *
5928 : * This method is the same as the C function OGR_F_Equal().
5929 : *
5930 : * @param poFeature the other feature to test this one against.
5931 : *
5932 : * @return TRUE if they are equal, otherwise FALSE.
5933 : */
5934 :
5935 56424 : OGRBoolean OGRFeature::Equal(const OGRFeature *poFeature) const
5936 :
5937 : {
5938 56424 : if (poFeature == this)
5939 1 : return TRUE;
5940 :
5941 56423 : if (GetFID() != poFeature->GetFID())
5942 53304 : return FALSE;
5943 :
5944 3119 : if (GetDefnRef() != poFeature->GetDefnRef())
5945 11 : return FALSE;
5946 :
5947 3108 : const int nFields = GetDefnRef()->GetFieldCountUnsafe();
5948 27306 : for (int i = 0; i < nFields; i++)
5949 : {
5950 24313 : if (IsFieldSet(i) != poFeature->IsFieldSet(i))
5951 2 : return FALSE;
5952 24311 : if (IsFieldNull(i) != poFeature->IsFieldNull(i))
5953 0 : return FALSE;
5954 24311 : if (!IsFieldSetAndNotNullUnsafe(i))
5955 3552 : continue;
5956 :
5957 20759 : switch (GetDefnRef()->GetFieldDefnUnsafe(i)->GetType())
5958 : {
5959 5672 : case OFTInteger:
5960 5672 : if (GetFieldAsInteger(i) != poFeature->GetFieldAsInteger(i))
5961 18 : return FALSE;
5962 5654 : break;
5963 :
5964 669 : case OFTInteger64:
5965 669 : if (GetFieldAsInteger64(i) != poFeature->GetFieldAsInteger64(i))
5966 4 : return FALSE;
5967 665 : break;
5968 :
5969 4250 : case OFTReal:
5970 : {
5971 4250 : const double dfVal1 = GetFieldAsDouble(i);
5972 4250 : const double dfVal2 = poFeature->GetFieldAsDouble(i);
5973 4250 : if (std::isnan(dfVal1))
5974 : {
5975 7 : if (!std::isnan(dfVal2))
5976 1 : return FALSE;
5977 : }
5978 4243 : else if (std::isnan(dfVal2))
5979 : {
5980 1 : return FALSE;
5981 : }
5982 4242 : else if (dfVal1 != dfVal2)
5983 : {
5984 16 : return FALSE;
5985 : }
5986 4232 : break;
5987 : }
5988 :
5989 5571 : case OFTString:
5990 5571 : if (strcmp(GetFieldAsString(i),
5991 5571 : poFeature->GetFieldAsString(i)) != 0)
5992 15 : return FALSE;
5993 5556 : break;
5994 :
5995 447 : case OFTIntegerList:
5996 : {
5997 447 : int nCount1 = 0;
5998 447 : int nCount2 = 0;
5999 447 : const int *pnList1 = GetFieldAsIntegerList(i, &nCount1);
6000 : const int *pnList2 =
6001 447 : poFeature->GetFieldAsIntegerList(i, &nCount2);
6002 447 : if (nCount1 != nCount2)
6003 4 : return FALSE;
6004 1247 : for (int j = 0; j < nCount1; j++)
6005 : {
6006 804 : if (pnList1[j] != pnList2[j])
6007 2 : return FALSE;
6008 : }
6009 443 : break;
6010 : }
6011 :
6012 168 : case OFTInteger64List:
6013 : {
6014 168 : int nCount1 = 0;
6015 168 : int nCount2 = 0;
6016 168 : const GIntBig *pnList1 = GetFieldAsInteger64List(i, &nCount1);
6017 : const GIntBig *pnList2 =
6018 168 : poFeature->GetFieldAsInteger64List(i, &nCount2);
6019 168 : if (nCount1 != nCount2)
6020 0 : return FALSE;
6021 497 : for (int j = 0; j < nCount1; j++)
6022 : {
6023 329 : if (pnList1[j] != pnList2[j])
6024 0 : return FALSE;
6025 : }
6026 168 : break;
6027 : }
6028 :
6029 326 : case OFTRealList:
6030 : {
6031 326 : int nCount1 = 0;
6032 326 : int nCount2 = 0;
6033 326 : const double *padfList1 = GetFieldAsDoubleList(i, &nCount1);
6034 : const double *padfList2 =
6035 326 : poFeature->GetFieldAsDoubleList(i, &nCount2);
6036 326 : if (nCount1 != nCount2)
6037 6 : return FALSE;
6038 928 : for (int j = 0; j < nCount1; j++)
6039 : {
6040 608 : const double dfVal1 = padfList1[j];
6041 608 : const double dfVal2 = padfList2[j];
6042 608 : if (std::isnan(dfVal1))
6043 : {
6044 126 : if (!std::isnan(dfVal2))
6045 1 : return FALSE;
6046 : }
6047 482 : else if (std::isnan(dfVal2))
6048 : {
6049 1 : return FALSE;
6050 : }
6051 481 : else if (dfVal1 != dfVal2)
6052 : {
6053 2 : return FALSE;
6054 : }
6055 : }
6056 320 : break;
6057 : }
6058 :
6059 170 : case OFTStringList:
6060 : {
6061 170 : int nCount1 = 0;
6062 170 : int nCount2 = 0;
6063 170 : char **papszList1 = GetFieldAsStringList(i);
6064 170 : char **papszList2 = poFeature->GetFieldAsStringList(i);
6065 170 : nCount1 = CSLCount(papszList1);
6066 170 : nCount2 = CSLCount(papszList2);
6067 170 : if (nCount1 != nCount2)
6068 2 : return FALSE;
6069 430 : for (int j = 0; j < nCount1; j++)
6070 : {
6071 264 : if (strcmp(papszList1[j], papszList2[j]) != 0)
6072 2 : return FALSE;
6073 : }
6074 166 : break;
6075 : }
6076 :
6077 1472 : case OFTTime:
6078 : case OFTDate:
6079 : case OFTDateTime:
6080 : {
6081 1472 : int nYear1 = 0;
6082 1472 : int nMonth1 = 0;
6083 1472 : int nDay1 = 0;
6084 1472 : int nHour1 = 0;
6085 1472 : int nMinute1 = 0;
6086 1472 : int nTZFlag1 = 0;
6087 1472 : int nYear2 = 0;
6088 1472 : int nMonth2 = 0;
6089 1472 : int nDay2 = 0;
6090 1472 : int nHour2 = 0;
6091 1472 : int nMinute2 = 0;
6092 1472 : int nTZFlag2 = 0;
6093 1472 : float fSecond1 = 0.0f;
6094 1472 : float fSecond2 = 0.0f;
6095 1472 : GetFieldAsDateTime(i, &nYear1, &nMonth1, &nDay1, &nHour1,
6096 : &nMinute1, &fSecond1, &nTZFlag1);
6097 1472 : poFeature->GetFieldAsDateTime(i, &nYear2, &nMonth2, &nDay2,
6098 : &nHour2, &nMinute2, &fSecond2,
6099 : &nTZFlag2);
6100 :
6101 1472 : if (!(nYear1 == nYear2 && nMonth1 == nMonth2 &&
6102 1460 : nDay1 == nDay2 && nHour1 == nHour2 &&
6103 1448 : nMinute1 == nMinute2 && fSecond1 == fSecond2 &&
6104 1436 : nTZFlag1 == nTZFlag2))
6105 42 : return FALSE;
6106 1430 : break;
6107 : }
6108 :
6109 2014 : case OFTBinary:
6110 : {
6111 2014 : int nCount1 = 0;
6112 2014 : int nCount2 = 0;
6113 2014 : GByte *pabyData1 = GetFieldAsBinary(i, &nCount1);
6114 2014 : GByte *pabyData2 = poFeature->GetFieldAsBinary(i, &nCount2);
6115 2014 : if (nCount1 != nCount2)
6116 2 : return FALSE;
6117 2012 : if (memcmp(pabyData1, pabyData2, nCount1) != 0)
6118 0 : return FALSE;
6119 2012 : break;
6120 : }
6121 :
6122 0 : default:
6123 0 : if (strcmp(GetFieldAsString(i),
6124 0 : poFeature->GetFieldAsString(i)) != 0)
6125 0 : return FALSE;
6126 0 : break;
6127 : }
6128 : }
6129 :
6130 2993 : const int nGeomFieldCount = GetGeomFieldCount();
6131 5682 : for (int i = 0; i < nGeomFieldCount; i++)
6132 : {
6133 2801 : const OGRGeometry *poThisGeom = GetGeomFieldRef(i);
6134 2801 : const OGRGeometry *poOtherGeom = poFeature->GetGeomFieldRef(i);
6135 :
6136 2801 : if (poThisGeom == nullptr && poOtherGeom != nullptr)
6137 3 : return FALSE;
6138 :
6139 2798 : if (poThisGeom != nullptr && poOtherGeom == nullptr)
6140 4 : return FALSE;
6141 :
6142 5408 : if (poThisGeom != nullptr && poOtherGeom != nullptr &&
6143 2614 : (!poThisGeom->Equals(poOtherGeom)))
6144 105 : return FALSE;
6145 : }
6146 :
6147 2881 : return TRUE;
6148 : }
6149 :
6150 : /************************************************************************/
6151 : /* OGR_F_Equal() */
6152 : /************************************************************************/
6153 :
6154 : /**
6155 : * \brief Test if two features are the same.
6156 : *
6157 : * Two features are considered equal if the share them (handle equality)
6158 : * same OGRFeatureDefn, have the same field values, and the same geometry
6159 : * (as tested by OGR_G_Equal()) as well as the same feature id.
6160 : *
6161 : * This function is the same as the C++ method OGRFeature::Equal().
6162 : *
6163 : * @param hFeat handle to one of the feature.
6164 : * @param hOtherFeat handle to the other feature to test this one against.
6165 : *
6166 : * @return TRUE if they are equal, otherwise FALSE.
6167 : */
6168 :
6169 109 : int OGR_F_Equal(OGRFeatureH hFeat, OGRFeatureH hOtherFeat)
6170 :
6171 : {
6172 109 : VALIDATE_POINTER1(hFeat, "OGR_F_Equal", 0);
6173 109 : VALIDATE_POINTER1(hOtherFeat, "OGR_F_Equal", 0);
6174 :
6175 218 : return OGRFeature::FromHandle(hFeat)->Equal(
6176 109 : OGRFeature::FromHandle(hOtherFeat));
6177 : }
6178 :
6179 : /************************************************************************/
6180 : /* SetFrom() */
6181 : /************************************************************************/
6182 :
6183 : /**
6184 : * \brief Set one feature from another.
6185 : *
6186 : * Overwrite the contents of this feature from the geometry and attributes
6187 : * of another. The poSrcFeature does not need to have the same
6188 : * OGRFeatureDefn. Field values are copied by corresponding field names.
6189 : * Field types do not have to exactly match. SetField() method conversion
6190 : * rules will be applied as needed.
6191 : *
6192 : * This method is the same as the C function OGR_F_SetFrom().
6193 : *
6194 : * @param poSrcFeature the feature from which geometry, and field values will
6195 : * be copied.
6196 : *
6197 : * @param bForgiving TRUE if the operation should continue despite lacking
6198 : * output fields matching some of the source fields.
6199 : *
6200 : * @return OGRERR_NONE if the operation succeeds, even if some values are
6201 : * not transferred, otherwise an error code.
6202 : */
6203 :
6204 4963 : OGRErr OGRFeature::SetFrom(const OGRFeature *poSrcFeature, int bForgiving)
6205 :
6206 : {
6207 4963 : const auto &oMap = poDefn->ComputeMapForSetFrom(poSrcFeature->GetDefnRef(),
6208 9926 : CPL_TO_BOOL(bForgiving));
6209 4963 : if (oMap.empty())
6210 : {
6211 262 : if (poSrcFeature->GetFieldCount())
6212 0 : return OGRERR_FAILURE;
6213 262 : int dummy = 0;
6214 262 : return SetFrom(poSrcFeature, &dummy, bForgiving);
6215 : }
6216 4701 : return SetFrom(poSrcFeature, oMap.data(), bForgiving);
6217 : }
6218 :
6219 : /************************************************************************/
6220 : /* OGR_F_SetFrom() */
6221 : /************************************************************************/
6222 :
6223 : /**
6224 : * \brief Set one feature from another.
6225 : *
6226 : * Overwrite the contents of this feature from the geometry and attributes
6227 : * of another. The hOtherFeature does not need to have the same
6228 : * OGRFeatureDefn. Field values are copied by corresponding field names.
6229 : * Field types do not have to exactly match. OGR_F_SetField*() function
6230 : * conversion rules will be applied as needed.
6231 : *
6232 : * This function is the same as the C++ method OGRFeature::SetFrom().
6233 : *
6234 : * @param hFeat handle to the feature to set to.
6235 : * @param hOtherFeat handle to the feature from which geometry,
6236 : * and field values will be copied.
6237 : *
6238 : * @param bForgiving TRUE if the operation should continue despite lacking
6239 : * output fields matching some of the source fields.
6240 : *
6241 : * @return OGRERR_NONE if the operation succeeds, even if some values are
6242 : * not transferred, otherwise an error code.
6243 : */
6244 :
6245 1812 : OGRErr OGR_F_SetFrom(OGRFeatureH hFeat, OGRFeatureH hOtherFeat, int bForgiving)
6246 :
6247 : {
6248 1812 : VALIDATE_POINTER1(hFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
6249 1812 : VALIDATE_POINTER1(hOtherFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
6250 :
6251 3624 : return OGRFeature::FromHandle(hFeat)->SetFrom(
6252 3624 : OGRFeature::FromHandle(hOtherFeat), bForgiving);
6253 : }
6254 :
6255 : /************************************************************************/
6256 : /* SetFrom() */
6257 : /************************************************************************/
6258 :
6259 : /**
6260 : * \brief Set one feature from another.
6261 : *
6262 : * Overwrite the contents of this feature from the geometry and attributes
6263 : * of another. The poSrcFeature does not need to have the same
6264 : * OGRFeatureDefn. Field values are copied according to the provided indices
6265 : * map. Field types do not have to exactly match. SetField() method
6266 : * conversion rules will be applied as needed. This is more efficient than
6267 : * OGR_F_SetFrom() in that this doesn't lookup the fields by their names.
6268 : * Particularly useful when the field names don't match.
6269 : *
6270 : * This method is the same as the C function OGR_F_SetFromWithMap().
6271 : *
6272 : * @param poSrcFeature the feature from which geometry, and field values will
6273 : * be copied.
6274 : *
6275 : * @param panMap Array of the indices of the feature's fields
6276 : * stored at the corresponding index of the source feature's fields. A value of
6277 : * -1 should be used to ignore the source's field. The array should not be NULL
6278 : * and be as long as the number of fields in the source feature.
6279 : *
6280 : * @param bForgiving TRUE if the operation should continue despite lacking
6281 : * output fields matching some of the source fields.
6282 : *
6283 : * @param bUseISO8601ForDateTimeAsString true if datetime fields
6284 : * converted to string should use ISO8601 formatting rather than OGR own format.
6285 : *
6286 : * @return OGRERR_NONE if the operation succeeds, even if some values are
6287 : * not transferred, otherwise an error code.
6288 : */
6289 :
6290 9230 : OGRErr OGRFeature::SetFrom(const OGRFeature *poSrcFeature, const int *panMap,
6291 : int bForgiving, bool bUseISO8601ForDateTimeAsString)
6292 :
6293 : {
6294 9230 : if (poSrcFeature == this)
6295 0 : return OGRERR_FAILURE;
6296 :
6297 9230 : SetFID(OGRNullFID);
6298 :
6299 : /* -------------------------------------------------------------------- */
6300 : /* Set the geometry. */
6301 : /* -------------------------------------------------------------------- */
6302 9230 : if (GetGeomFieldCount() == 1)
6303 : {
6304 7790 : const OGRGeomFieldDefn *poGFieldDefn = GetGeomFieldDefnRef(0);
6305 :
6306 7790 : int iSrc = poSrcFeature->GetGeomFieldIndex(poGFieldDefn->GetNameRef());
6307 7790 : if (iSrc >= 0)
6308 6434 : SetGeomField(0, poSrcFeature->GetGeomFieldRef(iSrc));
6309 : else
6310 : // Whatever the geometry field names are. For backward
6311 : // compatibility.
6312 1356 : SetGeomField(0, poSrcFeature->GetGeomFieldRef(0));
6313 : }
6314 : else
6315 : {
6316 2247 : for (int i = 0; i < GetGeomFieldCount(); i++)
6317 : {
6318 807 : const OGRGeomFieldDefn *poGFieldDefn = GetGeomFieldDefnRef(i);
6319 :
6320 : const int iSrc =
6321 807 : poSrcFeature->GetGeomFieldIndex(poGFieldDefn->GetNameRef());
6322 807 : if (iSrc >= 0)
6323 718 : SetGeomField(i, poSrcFeature->GetGeomFieldRef(iSrc));
6324 : else
6325 89 : SetGeomField(i, nullptr);
6326 : }
6327 : }
6328 :
6329 : /* -------------------------------------------------------------------- */
6330 : /* Copy feature style string. */
6331 : /* -------------------------------------------------------------------- */
6332 9230 : SetStyleString(poSrcFeature->GetStyleString());
6333 :
6334 : /* -------------------------------------------------------------------- */
6335 : /* Copy native data. */
6336 : /* -------------------------------------------------------------------- */
6337 9230 : SetNativeData(poSrcFeature->GetNativeData());
6338 9230 : SetNativeMediaType(poSrcFeature->GetNativeMediaType());
6339 :
6340 : /* -------------------------------------------------------------------- */
6341 : /* Set the fields by name. */
6342 : /* -------------------------------------------------------------------- */
6343 :
6344 9230 : const OGRErr eErr = SetFieldsFrom(poSrcFeature, panMap, bForgiving,
6345 : bUseISO8601ForDateTimeAsString);
6346 9230 : if (eErr != OGRERR_NONE)
6347 0 : return eErr;
6348 :
6349 9230 : return OGRERR_NONE;
6350 : }
6351 :
6352 : /************************************************************************/
6353 : /* OGR_F_SetFromWithMap() */
6354 : /************************************************************************/
6355 :
6356 : /**
6357 : * \brief Set one feature from another.
6358 : *
6359 : * Overwrite the contents of this feature from the geometry and attributes
6360 : * of another. The hOtherFeature does not need to have the same
6361 : * OGRFeatureDefn. Field values are copied according to the provided indices
6362 : * map. Field types do not have to exactly match. OGR_F_SetField*() function
6363 : * conversion rules will be applied as needed. This is more efficient than
6364 : * OGR_F_SetFrom() in that this doesn't lookup the fields by their names.
6365 : * Particularly useful when the field names don't match.
6366 : *
6367 : * This function is the same as the C++ method OGRFeature::SetFrom().
6368 : *
6369 : * @param hFeat handle to the feature to set to.
6370 : * @param hOtherFeat handle to the feature from which geometry,
6371 : * and field values will be copied.
6372 : *
6373 : * @param panMap Array of the indices of the destination feature's fields
6374 : * stored at the corresponding index of the source feature's fields. A value of
6375 : * -1 should be used to ignore the source's field. The array should not be NULL
6376 : * and be as long as the number of fields in the source feature.
6377 : *
6378 : * @param bForgiving TRUE if the operation should continue despite lacking
6379 : * output fields matching some of the source fields.
6380 : *
6381 : * @return OGRERR_NONE if the operation succeeds, even if some values are
6382 : * not transferred, otherwise an error code.
6383 : */
6384 :
6385 10 : OGRErr OGR_F_SetFromWithMap(OGRFeatureH hFeat, OGRFeatureH hOtherFeat,
6386 : int bForgiving, const int *panMap)
6387 :
6388 : {
6389 10 : VALIDATE_POINTER1(hFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
6390 10 : VALIDATE_POINTER1(hOtherFeat, "OGR_F_SetFrom", OGRERR_FAILURE);
6391 10 : VALIDATE_POINTER1(panMap, "OGR_F_SetFrom", OGRERR_FAILURE);
6392 :
6393 20 : return OGRFeature::FromHandle(hFeat)->SetFrom(
6394 20 : OGRFeature::FromHandle(hOtherFeat), panMap, bForgiving);
6395 : }
6396 :
6397 : /************************************************************************/
6398 : /* SetFieldsFrom() */
6399 : /************************************************************************/
6400 :
6401 : /**
6402 : * \brief Set fields from another feature.
6403 : *
6404 : * Overwrite the fields of this feature from the attributes of
6405 : * another. The FID and the style string are not set. The poSrcFeature
6406 : * does not need to have the same OGRFeatureDefn. Field values are
6407 : * copied according to the provided indices map. Field types do not
6408 : * have to exactly match. SetField() method conversion rules will be
6409 : * applied as needed. This is more efficient than OGR_F_SetFrom() in
6410 : * that this doesn't lookup the fields by their names. Particularly
6411 : * useful when the field names don't match.
6412 : *
6413 : * @param poSrcFeature the feature from which geometry, and field values will
6414 : * be copied.
6415 : *
6416 : * @param panMap Array of the indices of the feature's fields
6417 : * stored at the corresponding index of the source feature's fields. A value of
6418 : * -1 should be used to ignore the source's field. The array should not be NULL
6419 : * and be as long as the number of fields in the source feature.
6420 : *
6421 : * @param bForgiving TRUE if the operation should continue despite lacking
6422 : * output fields matching some of the source fields.
6423 : *
6424 : * @param bUseISO8601ForDateTimeAsString true if datetime fields
6425 : * converted to string should use ISO8601 formatting rather than OGR own format.
6426 : *
6427 : * @return OGRERR_NONE if the operation succeeds, even if some values are
6428 : * not transferred, otherwise an error code.
6429 : */
6430 :
6431 11097 : OGRErr OGRFeature::SetFieldsFrom(const OGRFeature *poSrcFeature,
6432 : const int *panMap, int bForgiving,
6433 : bool bUseISO8601ForDateTimeAsString)
6434 :
6435 : {
6436 11097 : const int nSrcFieldCount = poSrcFeature->poDefn->GetFieldCountUnsafe();
6437 11097 : const int nFieldCount = poDefn->GetFieldCountUnsafe();
6438 117481 : for (int iField = 0; iField < nSrcFieldCount; iField++)
6439 : {
6440 106384 : const int iDstField = panMap[iField];
6441 :
6442 106384 : if (iDstField < 0)
6443 3523 : continue;
6444 :
6445 102861 : if (nFieldCount <= iDstField)
6446 0 : return OGRERR_FAILURE;
6447 :
6448 102861 : if (!poSrcFeature->IsFieldSetUnsafe(iField))
6449 : {
6450 9476 : UnsetField(iDstField);
6451 9476 : continue;
6452 : }
6453 :
6454 93385 : if (poSrcFeature->IsFieldNullUnsafe(iField))
6455 : {
6456 1751 : SetFieldNull(iDstField);
6457 1751 : continue;
6458 : }
6459 :
6460 : const auto eSrcType =
6461 91634 : poSrcFeature->poDefn->GetFieldDefnUnsafe(iField)->GetType();
6462 91634 : const auto eDstType = poDefn->GetFieldDefnUnsafe(iDstField)->GetType();
6463 91634 : if (eSrcType == eDstType)
6464 : {
6465 88581 : if (eSrcType == OFTInteger)
6466 : {
6467 30735 : SetFieldSameTypeUnsafe(
6468 : iDstField, poSrcFeature->GetFieldAsIntegerUnsafe(iField));
6469 30735 : continue;
6470 : }
6471 57846 : if (eSrcType == OFTInteger64)
6472 : {
6473 3304 : SetFieldSameTypeUnsafe(
6474 : iDstField, poSrcFeature->GetFieldAsInteger64Unsafe(iField));
6475 3304 : continue;
6476 : }
6477 54542 : if (eSrcType == OFTReal)
6478 : {
6479 13344 : SetFieldSameTypeUnsafe(
6480 : iDstField, poSrcFeature->GetFieldAsDoubleUnsafe(iField));
6481 13344 : continue;
6482 : }
6483 41198 : if (eSrcType == OFTString)
6484 : {
6485 40409 : if (IsFieldSetAndNotNullUnsafe(iDstField))
6486 1505 : CPLFree(pauFields[iDstField].String);
6487 :
6488 40409 : SetFieldSameTypeUnsafe(
6489 : iDstField,
6490 : VSI_STRDUP_VERBOSE(
6491 : poSrcFeature->GetFieldAsStringUnsafe(iField)));
6492 40409 : continue;
6493 : }
6494 : }
6495 :
6496 : // Check if we must convert list types to JSON
6497 3842 : if (eDstType == OFTString)
6498 : {
6499 : const auto eDstSubType =
6500 61 : poDefn->GetFieldDefnUnsafe(iDstField)->GetSubType();
6501 61 : if (eDstSubType == OFSTJSON &&
6502 17 : (eSrcType == OFTIntegerList || eSrcType == OFTInteger64List ||
6503 6 : eSrcType == OFTRealList || eSrcType == OFTStringList))
6504 : {
6505 26 : char *pszVal = poSrcFeature->GetFieldAsSerializedJSon(iField);
6506 26 : if (pszVal)
6507 : {
6508 26 : SetField(iDstField, pszVal);
6509 26 : CPLFree(pszVal);
6510 26 : continue;
6511 : }
6512 : }
6513 : }
6514 :
6515 3816 : switch (eSrcType)
6516 : {
6517 1205 : case OFTInteger:
6518 1205 : SetField(iDstField,
6519 : poSrcFeature->GetFieldAsIntegerUnsafe(iField));
6520 1205 : break;
6521 :
6522 1613 : case OFTInteger64:
6523 1613 : SetField(iDstField,
6524 : poSrcFeature->GetFieldAsInteger64Unsafe(iField));
6525 1613 : break;
6526 :
6527 25 : case OFTReal:
6528 25 : SetField(iDstField,
6529 : poSrcFeature->GetFieldAsDoubleUnsafe(iField));
6530 25 : break;
6531 :
6532 86 : case OFTString:
6533 86 : SetField(iDstField,
6534 : poSrcFeature->GetFieldAsStringUnsafe(iField));
6535 86 : break;
6536 :
6537 270 : case OFTIntegerList:
6538 : {
6539 270 : if (eDstType == OFTString)
6540 : {
6541 2 : SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
6542 : }
6543 : else
6544 : {
6545 268 : int nCount = 0;
6546 : const int *panValues =
6547 268 : poSrcFeature->GetFieldAsIntegerList(iField, &nCount);
6548 268 : SetField(iDstField, nCount, panValues);
6549 : }
6550 : }
6551 270 : break;
6552 :
6553 47 : case OFTInteger64List:
6554 : {
6555 47 : if (eDstType == OFTString)
6556 : {
6557 1 : SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
6558 : }
6559 : else
6560 : {
6561 46 : int nCount = 0;
6562 : const GIntBig *panValues =
6563 46 : poSrcFeature->GetFieldAsInteger64List(iField, &nCount);
6564 46 : SetField(iDstField, nCount, panValues);
6565 : }
6566 : }
6567 47 : break;
6568 :
6569 86 : case OFTRealList:
6570 : {
6571 86 : if (eDstType == OFTString)
6572 : {
6573 2 : SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
6574 : }
6575 : else
6576 : {
6577 84 : int nCount = 0;
6578 : const double *padfValues =
6579 84 : poSrcFeature->GetFieldAsDoubleList(iField, &nCount);
6580 84 : SetField(iDstField, nCount, padfValues);
6581 : }
6582 : }
6583 86 : break;
6584 :
6585 412 : case OFTDate:
6586 : case OFTDateTime:
6587 : case OFTTime:
6588 : {
6589 412 : if (eDstType == OFTDate || eDstType == OFTTime ||
6590 : eDstType == OFTDateTime)
6591 : {
6592 380 : SetField(iDstField, poSrcFeature->GetRawFieldRef(iField));
6593 : }
6594 32 : else if (eDstType == OFTString || eDstType == OFTStringList)
6595 : {
6596 22 : SetField(iDstField,
6597 4 : eSrcType == OFTDateTime &&
6598 : bUseISO8601ForDateTimeAsString
6599 2 : ? poSrcFeature->GetFieldAsISO8601DateTime(
6600 : iField, nullptr)
6601 9 : : poSrcFeature->GetFieldAsString(iField));
6602 : }
6603 21 : else if (!bForgiving)
6604 0 : return OGRERR_FAILURE;
6605 412 : break;
6606 : }
6607 :
6608 72 : default:
6609 : {
6610 72 : if (eSrcType == eDstType)
6611 : {
6612 47 : SetField(iDstField, poSrcFeature->GetRawFieldRef(iField));
6613 : }
6614 25 : else if (eDstType == OFTString || eDstType == OFTStringList)
6615 : {
6616 6 : SetField(iDstField, poSrcFeature->GetFieldAsString(iField));
6617 : }
6618 19 : else if (!bForgiving)
6619 0 : return OGRERR_FAILURE;
6620 72 : break;
6621 : }
6622 : }
6623 : }
6624 :
6625 11097 : return OGRERR_NONE;
6626 : }
6627 :
6628 : /************************************************************************/
6629 : /* GetStyleString() */
6630 : /************************************************************************/
6631 :
6632 : /**
6633 : * \brief Fetch style string for this feature.
6634 : *
6635 : * Set the OGR Feature Style Specification for details on the format of
6636 : * this string, and ogr_featurestyle.h for services available to parse it.
6637 : *
6638 : * This method is the same as the C function OGR_F_GetStyleString().
6639 : *
6640 : * @return a reference to a representation in string format, or NULL if
6641 : * there isn't one.
6642 : */
6643 :
6644 61196 : const char *OGRFeature::GetStyleString() const
6645 : {
6646 61196 : if (m_pszStyleString)
6647 8731 : return m_pszStyleString;
6648 :
6649 52465 : const int iStyleFieldIndex = GetFieldIndex("OGR_STYLE");
6650 52465 : if (iStyleFieldIndex >= 0)
6651 62 : return GetFieldAsString(iStyleFieldIndex);
6652 :
6653 52403 : return nullptr;
6654 : }
6655 :
6656 : /************************************************************************/
6657 : /* OGR_F_GetStyleString() */
6658 : /************************************************************************/
6659 :
6660 : /**
6661 : * \brief Fetch style string for this feature.
6662 : *
6663 : * Set the OGR Feature Style Specification for details on the format of
6664 : * this string, and ogr_featurestyle.h for services available to parse it.
6665 : *
6666 : * This function is the same as the C++ method OGRFeature::GetStyleString().
6667 : *
6668 : * @param hFeat handle to the feature to get the style from.
6669 : * @return a reference to a representation in string format, or NULL if
6670 : * there isn't one.
6671 : */
6672 :
6673 1585 : const char *OGR_F_GetStyleString(OGRFeatureH hFeat)
6674 : {
6675 1585 : VALIDATE_POINTER1(hFeat, "OGR_F_GetStyleString", nullptr);
6676 :
6677 1585 : return OGRFeature::FromHandle(hFeat)->GetStyleString();
6678 : }
6679 :
6680 : /************************************************************************/
6681 : /* SetStyleString() */
6682 : /************************************************************************/
6683 :
6684 : /**
6685 : * \brief Set feature style string.
6686 : *
6687 : * This method operates the same as OGRFeature::SetStyleStringDirectly() except
6688 : * that it does not assume ownership of the passed string, but instead makes a
6689 : * copy of it.
6690 : *
6691 : * This method is the same as the C function OGR_F_SetStyleString().
6692 : *
6693 : * @param pszString the style string to apply to this feature, cannot be NULL.
6694 : */
6695 :
6696 339047 : void OGRFeature::SetStyleString(const char *pszString)
6697 : {
6698 339047 : if (m_pszStyleString)
6699 : {
6700 2364 : CPLFree(m_pszStyleString);
6701 2364 : m_pszStyleString = nullptr;
6702 : }
6703 :
6704 339047 : if (pszString)
6705 324476 : m_pszStyleString = VSI_STRDUP_VERBOSE(pszString);
6706 339047 : }
6707 :
6708 : /************************************************************************/
6709 : /* OGR_F_SetStyleString() */
6710 : /************************************************************************/
6711 :
6712 : /**
6713 : * \brief Set feature style string.
6714 : *
6715 : * This method operates the same as OGR_F_SetStyleStringDirectly() except that it
6716 : * does not assume ownership of the passed string, but instead makes a copy of
6717 : * it.
6718 : *
6719 : * This function is the same as the C++ method OGRFeature::SetStyleString().
6720 : *
6721 : * @param hFeat handle to the feature to set style to.
6722 : * @param pszStyle the style string to apply to this feature, cannot be NULL.
6723 : */
6724 :
6725 89 : void OGR_F_SetStyleString(OGRFeatureH hFeat, const char *pszStyle)
6726 :
6727 : {
6728 89 : VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleString");
6729 :
6730 89 : OGRFeature::FromHandle(hFeat)->SetStyleString(pszStyle);
6731 : }
6732 :
6733 : /************************************************************************/
6734 : /* SetStyleStringDirectly() */
6735 : /************************************************************************/
6736 :
6737 : /**
6738 : * \brief Set feature style string.
6739 : *
6740 : * This method operates the same as OGRFeature::SetStyleString() except that it
6741 : * assumes ownership of the passed string.
6742 : *
6743 : * This method is the same as the C function OGR_F_SetStyleStringDirectly().
6744 : *
6745 : * @param pszString the style string to apply to this feature, cannot be NULL.
6746 : */
6747 :
6748 0 : void OGRFeature::SetStyleStringDirectly(char *pszString)
6749 : {
6750 0 : CPLFree(m_pszStyleString);
6751 0 : m_pszStyleString = pszString;
6752 0 : }
6753 :
6754 : /************************************************************************/
6755 : /* OGR_F_SetStyleStringDirectly() */
6756 : /************************************************************************/
6757 :
6758 : /**
6759 : * \brief Set feature style string.
6760 : *
6761 : * This method operates the same as OGR_F_SetStyleString() except that it assumes
6762 : * ownership of the passed string.
6763 : *
6764 : * This function is the same as the C++ method
6765 : * OGRFeature::SetStyleStringDirectly().
6766 : *
6767 : * @param hFeat handle to the feature to set style to.
6768 : * @param pszStyle the style string to apply to this feature, cannot be NULL.
6769 : */
6770 :
6771 0 : void OGR_F_SetStyleStringDirectly(OGRFeatureH hFeat, char *pszStyle)
6772 :
6773 : {
6774 0 : VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleStringDirectly");
6775 :
6776 0 : OGRFeature::FromHandle(hFeat)->SetStyleStringDirectly(pszStyle);
6777 : }
6778 :
6779 : //************************************************************************/
6780 : /* SetStyleTable() */
6781 : /************************************************************************/
6782 :
6783 : /** Set style table.
6784 : * @param poStyleTable new style table (will be cloned)
6785 : */
6786 0 : void OGRFeature::SetStyleTable(OGRStyleTable *poStyleTable)
6787 : {
6788 0 : if (m_poStyleTable)
6789 0 : delete m_poStyleTable;
6790 0 : m_poStyleTable = poStyleTable ? poStyleTable->Clone() : nullptr;
6791 0 : }
6792 :
6793 : //************************************************************************/
6794 : /* SetStyleTableDirectly() */
6795 : /************************************************************************/
6796 :
6797 : /** Set style table.
6798 : * @param poStyleTable new style table (ownership transferred to the object)
6799 : */
6800 0 : void OGRFeature::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
6801 : {
6802 0 : if (m_poStyleTable)
6803 0 : delete m_poStyleTable;
6804 0 : m_poStyleTable = poStyleTable;
6805 0 : }
6806 :
6807 : //! @cond Doxygen_Suppress
6808 :
6809 : /************************************************************************/
6810 : /* RemapFields() */
6811 : /* */
6812 : /* This is used to transform a feature "in place" from one */
6813 : /* feature defn to another with minimum work. */
6814 : /************************************************************************/
6815 :
6816 50 : OGRErr OGRFeature::RemapFields(const OGRFeatureDefn *poNewDefn,
6817 : const int *panRemapSource)
6818 :
6819 : {
6820 50 : if (poNewDefn == nullptr)
6821 50 : poNewDefn = poDefn;
6822 :
6823 50 : const int nNewFieldCount = poNewDefn->GetFieldCount();
6824 : OGRField *pauNewFields =
6825 50 : static_cast<OGRField *>(CPLCalloc(nNewFieldCount, sizeof(OGRField)));
6826 :
6827 50 : const int nFieldCount = poDefn->GetFieldCount();
6828 318 : for (int iDstField = 0; iDstField < nFieldCount; iDstField++)
6829 : {
6830 268 : if (panRemapSource[iDstField] == -1)
6831 : {
6832 16 : OGR_RawField_SetUnset(&pauNewFields[iDstField]);
6833 : }
6834 : else
6835 : {
6836 252 : memcpy(pauNewFields + iDstField,
6837 252 : pauFields + panRemapSource[iDstField], sizeof(OGRField));
6838 : }
6839 : }
6840 :
6841 : // We really should be freeing memory for old columns that
6842 : // are no longer present. We don't for now because it is a bit messy
6843 : // and would take too long to test.
6844 :
6845 : /* -------------------------------------------------------------------- */
6846 : /* Apply new definition and fields. */
6847 : /* -------------------------------------------------------------------- */
6848 50 : CPLFree(pauFields);
6849 50 : pauFields = pauNewFields;
6850 :
6851 50 : poDefn = poNewDefn;
6852 :
6853 50 : return OGRERR_NONE;
6854 : }
6855 :
6856 : /************************************************************************/
6857 : /* AppendField() */
6858 : /* */
6859 : /* This is used to transform a feature "in place" by appending */
6860 : /* an unset field. */
6861 : /************************************************************************/
6862 :
6863 573 : void OGRFeature::AppendField()
6864 : {
6865 573 : const int nFieldCount = poDefn->GetFieldCountUnsafe();
6866 573 : pauFields = static_cast<OGRField *>(
6867 573 : CPLRealloc(pauFields, nFieldCount * sizeof(OGRField)));
6868 573 : OGR_RawField_SetUnset(&pauFields[nFieldCount - 1]);
6869 573 : }
6870 :
6871 : /************************************************************************/
6872 : /* RemapGeomFields() */
6873 : /* */
6874 : /* This is used to transform a feature "in place" from one */
6875 : /* feature defn to another with minimum work. */
6876 : /************************************************************************/
6877 :
6878 3 : OGRErr OGRFeature::RemapGeomFields(const OGRFeatureDefn *poNewDefn,
6879 : const int *panRemapSource)
6880 :
6881 : {
6882 3 : if (poNewDefn == nullptr)
6883 3 : poNewDefn = poDefn;
6884 :
6885 : OGRGeometry **papoNewGeomFields = static_cast<OGRGeometry **>(
6886 3 : CPLCalloc(poNewDefn->GetGeomFieldCount(), sizeof(OGRGeometry *)));
6887 :
6888 9 : for (int iDstField = 0; iDstField < poDefn->GetGeomFieldCount();
6889 : iDstField++)
6890 : {
6891 6 : if (panRemapSource[iDstField] == -1)
6892 : {
6893 3 : papoNewGeomFields[iDstField] = nullptr;
6894 : }
6895 : else
6896 : {
6897 3 : papoNewGeomFields[iDstField] =
6898 3 : papoGeometries[panRemapSource[iDstField]];
6899 : }
6900 : }
6901 :
6902 : // We really should be freeing memory for old columns that
6903 : // are no longer present. We don't for now because it is a bit messy
6904 : // and would take too long to test.
6905 :
6906 : /* -------------------------------------------------------------------- */
6907 : /* Apply new definition and fields. */
6908 : /* -------------------------------------------------------------------- */
6909 3 : CPLFree(papoGeometries);
6910 3 : papoGeometries = papoNewGeomFields;
6911 :
6912 3 : poDefn = poNewDefn;
6913 :
6914 3 : return OGRERR_NONE;
6915 : }
6916 :
6917 : //! @endcond
6918 :
6919 : /************************************************************************/
6920 : /* OGR_F_GetStyleTable() */
6921 : /************************************************************************/
6922 :
6923 0 : OGRStyleTableH OGR_F_GetStyleTable(OGRFeatureH hFeat)
6924 :
6925 : {
6926 0 : VALIDATE_POINTER1(hFeat, "OGR_F_GetStyleTable", nullptr);
6927 :
6928 : return reinterpret_cast<OGRStyleTableH>(
6929 0 : OGRFeature::FromHandle(hFeat)->GetStyleTable());
6930 : }
6931 :
6932 : /************************************************************************/
6933 : /* OGR_F_SetStyleTableDirectly() */
6934 : /************************************************************************/
6935 :
6936 0 : void OGR_F_SetStyleTableDirectly(OGRFeatureH hFeat, OGRStyleTableH hStyleTable)
6937 :
6938 : {
6939 0 : VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleTableDirectly");
6940 :
6941 0 : OGRFeature::FromHandle(hFeat)->SetStyleTableDirectly(
6942 0 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
6943 : }
6944 :
6945 : /************************************************************************/
6946 : /* OGR_F_SetStyleTable() */
6947 : /************************************************************************/
6948 :
6949 0 : void OGR_F_SetStyleTable(OGRFeatureH hFeat, OGRStyleTableH hStyleTable)
6950 :
6951 : {
6952 0 : VALIDATE_POINTER0(hFeat, "OGR_F_SetStyleTable");
6953 0 : VALIDATE_POINTER0(hStyleTable, "OGR_F_SetStyleTable");
6954 :
6955 0 : OGRFeature::FromHandle(hFeat)->SetStyleTable(
6956 0 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
6957 : }
6958 :
6959 : /************************************************************************/
6960 : /* FillUnsetWithDefault() */
6961 : /************************************************************************/
6962 :
6963 : /**
6964 : * \brief Fill unset fields with default values that might be defined.
6965 : *
6966 : * This method is the same as the C function OGR_F_FillUnsetWithDefault().
6967 : *
6968 : * @param bNotNullableOnly if we should fill only unset fields with a not-null
6969 : * constraint.
6970 : * @param papszOptions unused currently. Must be set to NULL.
6971 : */
6972 :
6973 277532 : void OGRFeature::FillUnsetWithDefault(int bNotNullableOnly,
6974 : CPL_UNUSED CSLConstList papszOptions)
6975 : {
6976 277532 : const int nFieldCount = poDefn->GetFieldCount();
6977 4755770 : for (int i = 0; i < nFieldCount; i++)
6978 : {
6979 4478240 : if (IsFieldSetUnsafe(i))
6980 4476680 : continue;
6981 1557 : const auto poFieldDefn = poDefn->GetFieldDefn(i);
6982 1557 : if (bNotNullableOnly && poFieldDefn->IsNullable())
6983 109 : continue;
6984 1448 : const char *pszDefault = poFieldDefn->GetDefault();
6985 1448 : OGRFieldType eType = poFieldDefn->GetType();
6986 1448 : if (pszDefault != nullptr)
6987 : {
6988 48 : if (eType == OFTDate || eType == OFTTime || eType == OFTDateTime)
6989 : {
6990 9 : if (STARTS_WITH_CI(pszDefault, "CURRENT"))
6991 : {
6992 4 : time_t t = time(nullptr);
6993 : struct tm brokendown;
6994 4 : CPLUnixTimeToYMDHMS(t, &brokendown);
6995 4 : SetField(i, brokendown.tm_year + 1900,
6996 4 : brokendown.tm_mon + 1, brokendown.tm_mday,
6997 : brokendown.tm_hour, brokendown.tm_min,
6998 4 : static_cast<float>(brokendown.tm_sec), 100);
6999 : }
7000 : else
7001 : {
7002 5 : int nYear = 0;
7003 5 : int nMonth = 0;
7004 5 : int nDay = 0;
7005 5 : int nHour = 0;
7006 5 : int nMinute = 0;
7007 5 : float fSecond = 0.0f;
7008 5 : if (sscanf(pszDefault, "'%d/%d/%d %d:%d:%f'", &nYear,
7009 5 : &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6)
7010 : {
7011 4 : SetField(i, nYear, nMonth, nDay, nHour, nMinute,
7012 : fSecond, 100);
7013 : }
7014 9 : }
7015 : }
7016 39 : else if (eType == OFTString && pszDefault[0] == '\'' &&
7017 8 : pszDefault[strlen(pszDefault) - 1] == '\'')
7018 : {
7019 16 : CPLString osDefault(pszDefault + 1);
7020 8 : osDefault.pop_back();
7021 8 : char *pszTmp = CPLUnescapeString(osDefault, nullptr, CPLES_SQL);
7022 8 : SetField(i, pszTmp);
7023 16 : CPLFree(pszTmp);
7024 : }
7025 31 : else if (!poFieldDefn->IsDefaultDriverSpecific())
7026 13 : SetField(i, pszDefault);
7027 : }
7028 : }
7029 277532 : }
7030 :
7031 : /************************************************************************/
7032 : /* OGR_F_FillUnsetWithDefault() */
7033 : /************************************************************************/
7034 :
7035 : /**
7036 : * \brief Fill unset fields with default values that might be defined.
7037 : *
7038 : * This function is the same as the C++ method
7039 : * OGRFeature::FillUnsetWithDefault().
7040 : *
7041 : * @param hFeat handle to the feature.
7042 : * @param bNotNullableOnly if we should fill only unset fields with a not-null
7043 : * constraint.
7044 : * @param papszOptions unused currently. Must be set to NULL.
7045 : */
7046 :
7047 2 : void OGR_F_FillUnsetWithDefault(OGRFeatureH hFeat, int bNotNullableOnly,
7048 : CSLConstList papszOptions)
7049 :
7050 : {
7051 2 : VALIDATE_POINTER0(hFeat, "OGR_F_FillUnsetWithDefault");
7052 :
7053 2 : OGRFeature::FromHandle(hFeat)->FillUnsetWithDefault(bNotNullableOnly,
7054 : papszOptions);
7055 : }
7056 :
7057 : /************************************************************************/
7058 : /* Validate() */
7059 : /************************************************************************/
7060 :
7061 : /**
7062 : * \brief Validate that a feature meets constraints of its schema.
7063 : *
7064 : * The scope of test is specified with the nValidateFlags parameter.
7065 : *
7066 : * Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width must be
7067 : * interpreted as the number of UTF-8 characters. Some drivers might interpret
7068 : * the width as the number of bytes instead. So this test is rather conservative
7069 : * (if it fails, then it will fail for all interpretations).
7070 : *
7071 : * This method is the same as the C function OGR_F_Validate().
7072 : *
7073 : * @param nValidateFlags OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
7074 : * OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and
7075 : * OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT,
7076 : * OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM with '|' operator
7077 : * @param bEmitError TRUE if a CPLError() must be emitted when a check fails
7078 : * @return TRUE if all enabled validation tests pass.
7079 : */
7080 :
7081 470 : int OGRFeature::Validate(int nValidateFlags, int bEmitError) const
7082 :
7083 : {
7084 470 : bool bRet = true;
7085 :
7086 470 : const int nGeomFieldCount = poDefn->GetGeomFieldCount();
7087 900 : for (int i = 0; i < nGeomFieldCount; i++)
7088 : {
7089 430 : if ((nValidateFlags & OGR_F_VAL_NULL) &&
7090 860 : !poDefn->GetGeomFieldDefn(i)->IsNullable() &&
7091 12 : GetGeomFieldRef(i) == nullptr)
7092 : {
7093 3 : bRet = false;
7094 3 : if (bEmitError)
7095 : {
7096 3 : CPLError(
7097 : CE_Failure, CPLE_AppDefined,
7098 : "Geometry field %s has a NULL content which is not allowed",
7099 3 : poDefn->GetGeomFieldDefn(i)->GetNameRef());
7100 : }
7101 : }
7102 603 : if ((nValidateFlags & OGR_F_VAL_GEOM_TYPE) &&
7103 173 : poDefn->GetGeomFieldDefn(i)->GetType() != wkbUnknown)
7104 : {
7105 136 : const OGRGeometry *poGeom = GetGeomFieldRef(i);
7106 136 : if (poGeom != nullptr)
7107 : {
7108 : const OGRwkbGeometryType eType =
7109 101 : poDefn->GetGeomFieldDefn(i)->GetType();
7110 101 : const OGRwkbGeometryType eFType = poGeom->getGeometryType();
7111 200 : if ((nValidateFlags & OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM) &&
7112 99 : (wkbFlatten(eFType) == wkbFlatten(eType) ||
7113 17 : wkbFlatten(eType) == wkbUnknown))
7114 : {
7115 : // Ok.
7116 : }
7117 32 : else if ((eType == wkbSetZ(wkbUnknown) && !wkbHasZ(eFType)) ||
7118 16 : (eType != wkbSetZ(wkbUnknown) && eFType != eType))
7119 : {
7120 15 : bRet = false;
7121 15 : if (bEmitError)
7122 : {
7123 30 : CPLError(CE_Failure, CPLE_AppDefined,
7124 : "Geometry field %s has a %s geometry whereas "
7125 : "%s is expected",
7126 15 : poDefn->GetGeomFieldDefn(i)->GetNameRef(),
7127 : OGRGeometryTypeToName(eFType),
7128 : OGRGeometryTypeToName(eType));
7129 : }
7130 : }
7131 : }
7132 : }
7133 : }
7134 470 : const int nFieldCount = poDefn->GetFieldCount();
7135 1670 : for (int i = 0; i < nFieldCount; i++)
7136 : {
7137 1200 : if ((nValidateFlags & OGR_F_VAL_NULL) &&
7138 2403 : !poDefn->GetFieldDefn(i)->IsNullable() && !IsFieldSet(i) &&
7139 3 : (!(nValidateFlags & OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT) ||
7140 2 : poDefn->GetFieldDefn(i)->GetDefault() == nullptr))
7141 : {
7142 3 : bRet = false;
7143 3 : if (bEmitError)
7144 : {
7145 6 : CPLError(CE_Failure, CPLE_AppDefined,
7146 : "Field %s.%s has a NULL content which is not allowed",
7147 3 : poDefn->GetName(),
7148 3 : poDefn->GetFieldDefn(i)->GetNameRef());
7149 : }
7150 : }
7151 630 : if ((nValidateFlags & OGR_F_VAL_WIDTH) &&
7152 866 : poDefn->GetFieldDefn(i)->GetWidth() > 0 &&
7153 308 : poDefn->GetFieldDefn(i)->GetType() == OFTString && IsFieldSet(i) &&
7154 1902 : CPLIsUTF8(GetFieldAsString(i), -1) &&
7155 72 : CPLStrlenUTF8Ex(GetFieldAsString(i)) >
7156 72 : static_cast<size_t>(poDefn->GetFieldDefn(i)->GetWidth()))
7157 : {
7158 1 : bRet = false;
7159 1 : if (bEmitError)
7160 : {
7161 3 : CPLError(
7162 : CE_Failure, CPLE_AppDefined,
7163 : "Field %s.%s has %" PRIu64 " UTF-8 characters whereas "
7164 : "a maximum of %d is allowed",
7165 1 : poDefn->GetName(), poDefn->GetFieldDefn(i)->GetNameRef(),
7166 1 : static_cast<uint64_t>(CPLStrlenUTF8Ex(GetFieldAsString(i))),
7167 1 : poDefn->GetFieldDefn(i)->GetWidth());
7168 : }
7169 : }
7170 : }
7171 :
7172 470 : return bRet;
7173 : }
7174 :
7175 : /************************************************************************/
7176 : /* OGR_F_Validate() */
7177 : /************************************************************************/
7178 :
7179 : /**
7180 : * \brief Validate that a feature meets constraints of its schema.
7181 : *
7182 : * The scope of test is specified with the nValidateFlags parameter.
7183 : *
7184 : * Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width must be
7185 : * interpreted as the number of UTF-8 characters. Some drivers might interpret
7186 : * the width as the number of bytes instead. So this test is rather conservative
7187 : * (if it fails, then it will fail for all interpretations).
7188 : *
7189 : * This function is the same as the C++ method
7190 : * OGRFeature::Validate().
7191 : *
7192 : * @param hFeat handle to the feature to validate.
7193 : * @param nValidateFlags OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
7194 : * OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and
7195 : * OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT with '|' operator
7196 : * @param bEmitError TRUE if a CPLError() must be emitted when a check fails
7197 : * @return TRUE if all enabled validation tests pass.
7198 : */
7199 :
7200 10 : int OGR_F_Validate(OGRFeatureH hFeat, int nValidateFlags, int bEmitError)
7201 :
7202 : {
7203 10 : VALIDATE_POINTER1(hFeat, "OGR_F_Validate", FALSE);
7204 :
7205 10 : return OGRFeature::FromHandle(hFeat)->Validate(nValidateFlags, bEmitError);
7206 : }
7207 :
7208 : /************************************************************************/
7209 : /* GetNativeData() */
7210 : /************************************************************************/
7211 :
7212 : /**
7213 : * \fn const char* OGRFeature::GetNativeData() const;
7214 : *
7215 : * \brief Returns the native data for the feature.
7216 : *
7217 : * The native data is the representation in a "natural" form that comes from
7218 : * the driver that created this feature, or that is aimed at an output driver.
7219 : * The native data may be in different format, which is indicated by
7220 : * GetNativeMediaType().
7221 : *
7222 : * Note that most drivers do not support storing the native data in the feature
7223 : * object, and if they do, generally the NATIVE_DATA open option must be passed
7224 : * at dataset opening.
7225 : *
7226 : * The "native data" does not imply it is something more performant or powerful
7227 : * than what can be obtained with the rest of the API, but it may be useful in
7228 : * round-tripping scenarios where some characteristics of the underlying format
7229 : * are not captured otherwise by the OGR abstraction.
7230 : *
7231 : * This function is the same as the C function
7232 : * OGR_F_GetNativeData().
7233 : *
7234 : * @return a string with the native data, or NULL if there is none.
7235 : *
7236 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7237 : */
7238 :
7239 : /************************************************************************/
7240 : /* OGR_F_GetNativeData() */
7241 : /************************************************************************/
7242 :
7243 : /**
7244 : * \brief Returns the native data for the feature.
7245 : *
7246 : * The native data is the representation in a "natural" form that comes from
7247 : * the driver that created this feature, or that is aimed at an output driver.
7248 : * The native data may be in different format, which is indicated by
7249 : * OGR_F_GetNativeMediaType().
7250 : *
7251 : * Note that most drivers do not support storing the native data in the feature
7252 : * object, and if they do, generally the NATIVE_DATA open option must be passed
7253 : * at dataset opening.
7254 : *
7255 : * The "native data" does not imply it is something more performant or powerful
7256 : * than what can be obtained with the rest of the API, but it may be useful in
7257 : * round-tripping scenarios where some characteristics of the underlying format
7258 : * are not captured otherwise by the OGR abstraction.
7259 : *
7260 : * This function is the same as the C++ method
7261 : * OGRFeature::GetNativeData().
7262 : *
7263 : * @param hFeat handle to the feature.
7264 : * @return a string with the native data, or NULL if there is none.
7265 : *
7266 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7267 : */
7268 :
7269 9 : const char *OGR_F_GetNativeData(OGRFeatureH hFeat)
7270 :
7271 : {
7272 9 : VALIDATE_POINTER1(hFeat, "OGR_F_GetNativeData", nullptr);
7273 :
7274 9 : return OGRFeature::FromHandle(hFeat)->GetNativeData();
7275 : }
7276 :
7277 : /************************************************************************/
7278 : /* GetNativeMediaType() */
7279 : /************************************************************************/
7280 :
7281 : /**
7282 : * \fn const char* OGRFeature::GetNativeMediaType() const;
7283 : *
7284 : * \brief Returns the native media type for the feature.
7285 : *
7286 : * The native media type is the identifier for the format of the native data.
7287 : * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
7288 : * e.g. "application/vnd.geo+json" for JSon.
7289 : *
7290 : * This function is the same as the C function
7291 : * OGR_F_GetNativeMediaType().
7292 : *
7293 : * @return a string with the native media type, or NULL if there is none.
7294 : *
7295 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7296 : */
7297 :
7298 : /************************************************************************/
7299 : /* OGR_F_GetNativeMediaType() */
7300 : /************************************************************************/
7301 :
7302 : /**
7303 : * \brief Returns the native media type for the feature.
7304 : *
7305 : * The native media type is the identifier for the format of the native data.
7306 : * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
7307 : * e.g. "application/vnd.geo+json" for JSon.
7308 : *
7309 : * This function is the same as the C function
7310 : * OGR_F_GetNativeMediaType().
7311 : *
7312 : * @param hFeat handle to the feature.
7313 : * @return a string with the native media type, or NULL if there is none.
7314 : *
7315 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7316 : */
7317 :
7318 9 : const char *OGR_F_GetNativeMediaType(OGRFeatureH hFeat)
7319 : {
7320 9 : VALIDATE_POINTER1(hFeat, "OGR_F_GetNativeMediaType", nullptr);
7321 :
7322 9 : return OGRFeature::FromHandle(hFeat)->GetNativeMediaType();
7323 : }
7324 :
7325 : /************************************************************************/
7326 : /* SetNativeData() */
7327 : /************************************************************************/
7328 :
7329 : /**
7330 : * \brief Sets the native data for the feature.
7331 : *
7332 : * The native data is the representation in a "natural" form that comes from
7333 : * the driver that created this feature, or that is aimed at an output driver.
7334 : * The native data may be in different format, which is indicated by
7335 : * GetNativeMediaType().
7336 : *
7337 : * This function is the same as the C function
7338 : * OGR_F_SetNativeData().
7339 : *
7340 : * @param pszNativeData a string with the native data, or NULL if there is none.
7341 : *
7342 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7343 : */
7344 :
7345 14969 : void OGRFeature::SetNativeData(const char *pszNativeData)
7346 : {
7347 14969 : CPLFree(m_pszNativeData);
7348 14969 : m_pszNativeData =
7349 14969 : pszNativeData ? VSI_STRDUP_VERBOSE(pszNativeData) : nullptr;
7350 14969 : }
7351 :
7352 : /************************************************************************/
7353 : /* OGR_F_SetNativeData() */
7354 : /************************************************************************/
7355 :
7356 : /**
7357 : * \brief Sets the native data for the feature.
7358 : *
7359 : * The native data is the representation in a "natural" form that comes from
7360 : * the driver that created this feature, or that is aimed at an output driver.
7361 : * The native data may be in different format, which is indicated by
7362 : * OGR_F_GetNativeMediaType().
7363 : *
7364 : * This function is the same as the C++ method
7365 : * OGRFeature::SetNativeData().
7366 : *
7367 : * @param hFeat handle to the feature.
7368 : * @param pszNativeData a string with the native data, or NULL if there is none.
7369 : *
7370 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7371 : */
7372 :
7373 4 : void OGR_F_SetNativeData(OGRFeatureH hFeat, const char *pszNativeData)
7374 : {
7375 4 : VALIDATE_POINTER0(hFeat, "OGR_F_SetNativeData");
7376 :
7377 4 : OGRFeature::FromHandle(hFeat)->SetNativeData(pszNativeData);
7378 : }
7379 :
7380 : /************************************************************************/
7381 : /* SetNativeMediaType() */
7382 : /************************************************************************/
7383 :
7384 : /**
7385 : * \brief Sets the native media type for the feature.
7386 : *
7387 : * The native media type is the identifier for the format of the native data.
7388 : * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
7389 : * e.g. "application/vnd.geo+json" for JSon.
7390 : *
7391 : * This function is the same as the C function
7392 : * OGR_F_SetNativeMediaType().
7393 : *
7394 : * @param pszNativeMediaType a string with the native media type, or NULL if
7395 : * there is none.
7396 : *
7397 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7398 : */
7399 :
7400 14969 : void OGRFeature::SetNativeMediaType(const char *pszNativeMediaType)
7401 : {
7402 14969 : CPLFree(m_pszNativeMediaType);
7403 14969 : m_pszNativeMediaType =
7404 14969 : pszNativeMediaType ? VSI_STRDUP_VERBOSE(pszNativeMediaType) : nullptr;
7405 14969 : }
7406 :
7407 : /************************************************************************/
7408 : /* OGR_F_SetNativeMediaType() */
7409 : /************************************************************************/
7410 :
7411 : /**
7412 : * \brief Sets the native media type for the feature.
7413 : *
7414 : * The native media type is the identifier for the format of the native data.
7415 : * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
7416 : * e.g. "application/vnd.geo+json" for JSon.
7417 : *
7418 : * This function is the same as the C++ method
7419 : * OGRFeature::SetNativeMediaType().
7420 : *
7421 : * @param hFeat handle to the feature.
7422 : * @param pszNativeMediaType a string with the native media type, or NULL if
7423 : * there is none.
7424 : *
7425 : * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
7426 : */
7427 :
7428 4 : void OGR_F_SetNativeMediaType(OGRFeatureH hFeat, const char *pszNativeMediaType)
7429 : {
7430 4 : VALIDATE_POINTER0(hFeat, "OGR_F_SetNativeMediaType");
7431 :
7432 4 : OGRFeature::FromHandle(hFeat)->SetNativeMediaType(pszNativeMediaType);
7433 : }
7434 :
7435 : /************************************************************************/
7436 : /* OGR_RawField_IsUnset() */
7437 : /************************************************************************/
7438 :
7439 : /**
7440 : * \brief Returns whether a raw field is unset.
7441 : *
7442 : * Note: this function is rather low-level and should be rarely used in client
7443 : * code. Use instead OGR_F_IsFieldSet().
7444 : *
7445 : * @param puField pointer to raw field.
7446 : */
7447 :
7448 3741500 : int OGR_RawField_IsUnset(const OGRField *puField)
7449 : {
7450 5176590 : return puField->Set.nMarker1 == OGRUnsetMarker &&
7451 5176590 : puField->Set.nMarker2 == OGRUnsetMarker &&
7452 5176590 : puField->Set.nMarker3 == OGRUnsetMarker;
7453 : }
7454 :
7455 : /************************************************************************/
7456 : /* OGR_RawField_IsNull() */
7457 : /************************************************************************/
7458 :
7459 : /**
7460 : * \brief Returns whether a raw field is null.
7461 : *
7462 : * Note: this function is rather low-level and should be rarely used in client
7463 : * code. Use instead OGR_F_IsFieldNull().
7464 : *
7465 : * @param puField pointer to raw field.
7466 : */
7467 :
7468 2293460 : int OGR_RawField_IsNull(const OGRField *puField)
7469 : {
7470 2298180 : return puField->Set.nMarker1 == OGRNullMarker &&
7471 2298180 : puField->Set.nMarker2 == OGRNullMarker &&
7472 2298180 : puField->Set.nMarker3 == OGRNullMarker;
7473 : }
7474 :
7475 : /************************************************************************/
7476 : /* OGR_RawField_SetUnset() */
7477 : /************************************************************************/
7478 :
7479 : /**
7480 : * \brief Mark a raw field as unset.
7481 : *
7482 : * This should be called on a un-initialized field. In particular this will not
7483 : * free any memory dynamically allocated.
7484 : *
7485 : * Note: this function is rather low-level and should be rarely used in client
7486 : * code. Use instead OGR_F_UnsetField().
7487 : *
7488 : * @param puField pointer to raw field.
7489 : */
7490 :
7491 116088 : void OGR_RawField_SetUnset(OGRField *puField)
7492 : {
7493 116088 : puField->Set.nMarker1 = OGRUnsetMarker;
7494 116088 : puField->Set.nMarker2 = OGRUnsetMarker;
7495 116088 : puField->Set.nMarker3 = OGRUnsetMarker;
7496 116088 : }
7497 :
7498 : /************************************************************************/
7499 : /* OGR_RawField_SetNull() */
7500 : /************************************************************************/
7501 :
7502 : /**
7503 : * \brief Mark a raw field as null.
7504 : *
7505 : * This should be called on a un-initialized field. In particular this will not
7506 : * free any memory dynamically allocated.
7507 : *
7508 : * Note: this function is rather low-level and should be rarely used in client
7509 : * code. Use instead OGR_F_SetFieldNull().
7510 : *
7511 : * @param puField pointer to raw field.
7512 : */
7513 :
7514 57151 : void OGR_RawField_SetNull(OGRField *puField)
7515 : {
7516 57151 : puField->Set.nMarker1 = OGRNullMarker;
7517 57151 : puField->Set.nMarker2 = OGRNullMarker;
7518 57151 : puField->Set.nMarker3 = OGRNullMarker;
7519 57151 : }
7520 :
7521 : /************************************************************************/
7522 : /* OGRFeatureUniquePtrDeleter */
7523 : /************************************************************************/
7524 :
7525 : //! @cond Doxygen_Suppress
7526 166844 : void OGRFeatureUniquePtrDeleter::operator()(OGRFeature *poFeature) const
7527 : {
7528 166844 : delete poFeature;
7529 166844 : }
7530 :
7531 : //! @endcond
7532 :
7533 : namespace
7534 : {
7535 : // Implementation borrowed to OpenFileGDB
7536 :
7537 : /************************************************************************/
7538 : /* WriteUInt8() */
7539 : /************************************************************************/
7540 :
7541 11025 : inline void WriteUInt8(std::vector<GByte> &abyBuffer, uint8_t nVal)
7542 : {
7543 11025 : abyBuffer.push_back(nVal);
7544 11025 : }
7545 :
7546 : /************************************************************************/
7547 : /* WriteVarUInt() */
7548 : /************************************************************************/
7549 :
7550 5789 : inline void WriteVarUInt(std::vector<GByte> &abyBuffer, uint64_t nVal)
7551 : {
7552 : while (true)
7553 : {
7554 5789 : if (nVal >= 0x80)
7555 : {
7556 16 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nVal & 0x7F)));
7557 16 : nVal >>= 7;
7558 : }
7559 : else
7560 : {
7561 5773 : WriteUInt8(abyBuffer, static_cast<uint8_t>(nVal));
7562 5773 : break;
7563 : }
7564 : }
7565 5773 : }
7566 :
7567 : /************************************************************************/
7568 : /* WriteVarInt() */
7569 : /************************************************************************/
7570 :
7571 5226 : inline void WriteVarInt(std::vector<GByte> &abyBuffer, int64_t nVal)
7572 : {
7573 : uint64_t nUVal;
7574 5226 : if (nVal < 0)
7575 : {
7576 7 : if (nVal == std::numeric_limits<int64_t>::min())
7577 0 : nUVal = static_cast<uint64_t>(1) << 63;
7578 : else
7579 7 : nUVal = -nVal;
7580 7 : if (nUVal >= 0x40)
7581 : {
7582 5 : WriteUInt8(abyBuffer,
7583 5 : static_cast<uint8_t>(0x80 | 0x40 | (nUVal & 0x3F)));
7584 5 : nUVal >>= 6;
7585 : }
7586 : else
7587 : {
7588 2 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x40 | (nUVal & 0x3F)));
7589 2 : return;
7590 : }
7591 : }
7592 : else
7593 : {
7594 5219 : nUVal = nVal;
7595 5219 : if (nUVal >= 0x40)
7596 : {
7597 4170 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nUVal & 0x3F)));
7598 4170 : nUVal >>= 6;
7599 : }
7600 : else
7601 : {
7602 1049 : WriteUInt8(abyBuffer, static_cast<uint8_t>((nUVal & 0x3F)));
7603 1049 : return;
7604 : }
7605 : }
7606 :
7607 4175 : WriteVarUInt(abyBuffer, nUVal);
7608 : }
7609 :
7610 : /************************************************************************/
7611 : /* WriteFloat32() */
7612 : /************************************************************************/
7613 :
7614 2 : inline void WriteFloat32(std::vector<GByte> &abyBuffer, float fVal)
7615 : {
7616 2 : CPL_LSBPTR32(&fVal);
7617 2 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&fVal);
7618 2 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(fVal));
7619 2 : }
7620 :
7621 : /************************************************************************/
7622 : /* WriteFloat64() */
7623 : /************************************************************************/
7624 :
7625 3 : inline void WriteFloat64(std::vector<GByte> &abyBuffer, double dfVal)
7626 : {
7627 3 : CPL_LSBPTR64(&dfVal);
7628 3 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&dfVal);
7629 3 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(dfVal));
7630 3 : }
7631 :
7632 : } // namespace
7633 :
7634 : /************************************************************************/
7635 : /* OGRFeature::SerializeToBinary() */
7636 : /************************************************************************/
7637 :
7638 : /** Serialize the feature to a binary encoding.
7639 : *
7640 : * This saves the feature ID, attribute fields content and geometry fields
7641 : * content.
7642 : *
7643 : * This method is aimed at being paired with DeserializeFromBinary().
7644 : *
7645 : * The format of that encoding may vary across GDAL versions.
7646 : *
7647 : * Note that abyBuffer is cleared at the beginning of this function.
7648 : *
7649 : * @since 3.9
7650 : */
7651 2609 : bool OGRFeature::SerializeToBinary(std::vector<GByte> &abyBuffer) const
7652 : {
7653 2609 : const int nFieldCount = poDefn->GetFieldCount();
7654 2609 : const int nGeomFieldCount = poDefn->GetGeomFieldCount();
7655 : try
7656 : {
7657 2609 : abyBuffer.clear();
7658 : // Set field flags
7659 : // For attribute fields, we have 2 bits
7660 : // - first one set if the field is unset
7661 : // - second one set if the field is null
7662 : // For geometry fields, we have one bit set to indicate if the geometry
7663 : // is non-null.
7664 2609 : const size_t nPresenceFlagsSize =
7665 2609 : ((2 * nFieldCount + nGeomFieldCount) + 7) / 8;
7666 2609 : abyBuffer.resize(nPresenceFlagsSize);
7667 :
7668 2609 : WriteVarInt(abyBuffer, GetFID());
7669 :
7670 1036 : const auto SetFlagBit = [&abyBuffer](int iBit)
7671 1036 : { abyBuffer[iBit / 8] |= (1 << (iBit % 8)); };
7672 :
7673 5249 : for (int i = 0; i < nFieldCount; ++i)
7674 : {
7675 2640 : const OGRField &uField = pauFields[i];
7676 2640 : if (OGR_RawField_IsUnset(&uField))
7677 : {
7678 23 : const int iBit = 2 * i;
7679 23 : SetFlagBit(iBit);
7680 23 : continue;
7681 : }
7682 2617 : if (OGR_RawField_IsNull(&uField))
7683 : {
7684 1 : const int iBit = 2 * i + 1;
7685 1 : SetFlagBit(iBit);
7686 1 : continue;
7687 : }
7688 2616 : const auto poFDefn = poDefn->GetFieldDefn(i);
7689 2616 : switch (poFDefn->GetType())
7690 : {
7691 2605 : case OFTInteger:
7692 : {
7693 2605 : WriteVarInt(abyBuffer, uField.Integer);
7694 2605 : break;
7695 : }
7696 1 : case OFTInteger64:
7697 : {
7698 1 : WriteVarInt(abyBuffer, uField.Integer64);
7699 1 : break;
7700 : }
7701 1 : case OFTReal:
7702 : {
7703 1 : WriteFloat64(abyBuffer, uField.Real);
7704 1 : break;
7705 : }
7706 1 : case OFTString:
7707 : {
7708 1 : const size_t nStrSize = strlen(uField.String);
7709 1 : WriteVarUInt(abyBuffer, nStrSize);
7710 1 : const GByte *pabyStr =
7711 : reinterpret_cast<const GByte *>(uField.String);
7712 0 : abyBuffer.insert(abyBuffer.end(), pabyStr,
7713 1 : pabyStr + nStrSize);
7714 1 : break;
7715 : }
7716 1 : case OFTIntegerList:
7717 : {
7718 1 : WriteVarInt(abyBuffer, uField.IntegerList.nCount);
7719 3 : for (int j = 0; j < uField.IntegerList.nCount; ++j)
7720 2 : WriteVarInt(abyBuffer, uField.IntegerList.paList[j]);
7721 1 : break;
7722 : }
7723 1 : case OFTInteger64List:
7724 : {
7725 1 : WriteVarInt(abyBuffer, uField.Integer64List.nCount);
7726 3 : for (int j = 0; j < uField.Integer64List.nCount; ++j)
7727 2 : WriteVarInt(abyBuffer, uField.Integer64List.paList[j]);
7728 1 : break;
7729 : }
7730 1 : case OFTRealList:
7731 : {
7732 1 : WriteVarInt(abyBuffer, uField.RealList.nCount);
7733 3 : for (int j = 0; j < uField.RealList.nCount; ++j)
7734 2 : WriteFloat64(abyBuffer, uField.RealList.paList[j]);
7735 1 : break;
7736 : }
7737 1 : case OFTStringList:
7738 : {
7739 1 : WriteVarInt(abyBuffer, uField.StringList.nCount);
7740 3 : for (int j = 0; j < uField.StringList.nCount; ++j)
7741 : {
7742 2 : const char *pszStr = uField.StringList.paList[j];
7743 2 : const size_t nStrSize = strlen(pszStr);
7744 2 : WriteVarUInt(abyBuffer, nStrSize);
7745 2 : const GByte *pabyStr =
7746 : reinterpret_cast<const GByte *>(pszStr);
7747 0 : abyBuffer.insert(abyBuffer.end(), pabyStr,
7748 2 : pabyStr + nStrSize);
7749 : }
7750 1 : break;
7751 : }
7752 1 : case OFTBinary:
7753 : {
7754 1 : WriteVarInt(abyBuffer, uField.Binary.nCount);
7755 0 : abyBuffer.insert(abyBuffer.end(), uField.Binary.paData,
7756 1 : uField.Binary.paData +
7757 1 : uField.Binary.nCount);
7758 1 : break;
7759 : }
7760 0 : case OFTWideString:
7761 : case OFTWideStringList:
7762 0 : break;
7763 1 : case OFTDate:
7764 : {
7765 1 : WriteVarInt(abyBuffer, uField.Date.Year);
7766 1 : WriteUInt8(abyBuffer, uField.Date.Month);
7767 1 : WriteUInt8(abyBuffer, uField.Date.Day);
7768 1 : break;
7769 : }
7770 1 : case OFTTime:
7771 : {
7772 1 : WriteUInt8(abyBuffer, uField.Date.Hour);
7773 1 : WriteUInt8(abyBuffer, uField.Date.Minute);
7774 1 : WriteFloat32(abyBuffer, uField.Date.Second);
7775 1 : WriteUInt8(abyBuffer, uField.Date.TZFlag);
7776 1 : break;
7777 : }
7778 1 : case OFTDateTime:
7779 : {
7780 1 : WriteVarInt(abyBuffer, uField.Date.Year);
7781 1 : WriteUInt8(abyBuffer, uField.Date.Month);
7782 1 : WriteUInt8(abyBuffer, uField.Date.Day);
7783 1 : WriteUInt8(abyBuffer, uField.Date.Hour);
7784 1 : WriteUInt8(abyBuffer, uField.Date.Minute);
7785 1 : WriteFloat32(abyBuffer, uField.Date.Second);
7786 1 : WriteUInt8(abyBuffer, uField.Date.TZFlag);
7787 1 : break;
7788 : }
7789 : }
7790 : }
7791 5216 : for (int i = 0; i < nGeomFieldCount; ++i)
7792 : {
7793 2607 : if (!papoGeometries[i])
7794 : {
7795 1012 : const int iBit = 2 * nFieldCount + i;
7796 1012 : SetFlagBit(iBit);
7797 1012 : continue;
7798 : }
7799 1595 : const size_t nSize = papoGeometries[i]->WkbSize();
7800 1595 : WriteVarUInt(abyBuffer, nSize);
7801 1595 : const size_t nBufSizeBefore = abyBuffer.size();
7802 1595 : abyBuffer.resize(nBufSizeBefore + nSize);
7803 1595 : papoGeometries[i]->exportToWkb(
7804 1595 : wkbNDR, abyBuffer.data() + nBufSizeBefore, wkbVariantIso);
7805 : }
7806 2609 : return true;
7807 : }
7808 0 : catch (const std::bad_alloc &)
7809 : {
7810 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
7811 0 : return false;
7812 : }
7813 : }
7814 :
7815 : namespace
7816 : {
7817 : // Implementation borrowed to OpenFileGDB
7818 :
7819 : /************************************************************************/
7820 : /* ReadVarUInt() */
7821 : /************************************************************************/
7822 :
7823 : template <class OutType>
7824 2197 : static bool ReadVarUInt(const GByte *&pabyIter, const GByte *pabyEnd,
7825 : OutType &nOutVal)
7826 : {
7827 2197 : if (pabyIter >= pabyEnd)
7828 3 : return false;
7829 2194 : OutType b = *pabyIter;
7830 2194 : if ((b & 0x80) == 0)
7831 : {
7832 2189 : pabyIter++;
7833 2189 : nOutVal = b;
7834 2189 : return true;
7835 : }
7836 5 : const GByte *pabyLocalIter = pabyIter + 1;
7837 5 : int nShift = 7;
7838 5 : OutType nVal = (b & 0x7F);
7839 : while (true)
7840 : {
7841 5 : if (pabyLocalIter >= pabyEnd)
7842 0 : return false;
7843 5 : b = *pabyLocalIter;
7844 5 : pabyLocalIter++;
7845 5 : nVal |= (b & 0x7F) << nShift;
7846 5 : if ((b & 0x80) == 0)
7847 : {
7848 5 : pabyIter = pabyLocalIter;
7849 5 : nOutVal = nVal;
7850 5 : return true;
7851 : }
7852 0 : nShift += 7;
7853 : // To avoid undefined behavior later when doing << nShift
7854 0 : if (nShift >= static_cast<int>(sizeof(OutType)) * 8)
7855 : {
7856 0 : return false;
7857 : }
7858 : }
7859 : }
7860 :
7861 : /************************************************************************/
7862 : /* ReadVarInt() */
7863 : /************************************************************************/
7864 :
7865 : template <class OutType>
7866 : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW static bool
7867 7811 : ReadVarInt(const GByte *&pabyIter, const GByte *pabyEnd, OutType &nOutVal)
7868 : {
7869 : GUInt32 b;
7870 :
7871 7811 : if (pabyIter >= pabyEnd)
7872 15 : return false;
7873 7796 : b = *pabyIter;
7874 7796 : GUIntBig nVal = (b & 0x3F);
7875 7796 : bool bNegative = (b & 0x40) != 0;
7876 7796 : if ((b & 0x80) == 0)
7877 : {
7878 2545 : pabyIter++;
7879 2545 : if (bNegative)
7880 4 : nOutVal = -static_cast<OutType>(nVal);
7881 : else
7882 2541 : nOutVal = static_cast<OutType>(nVal);
7883 2545 : return true;
7884 : }
7885 :
7886 5251 : const GByte *pabyLocalIter = pabyIter + 1;
7887 5251 : int nShift = 6;
7888 2179 : while (true)
7889 : {
7890 7430 : if (pabyLocalIter >= pabyEnd)
7891 23 : return false;
7892 7407 : GUIntBig b64 = *pabyLocalIter;
7893 7407 : pabyLocalIter++;
7894 7407 : nVal |= (b64 & 0x7F) << nShift;
7895 7407 : if ((b64 & 0x80) == 0)
7896 : {
7897 5228 : pabyIter = pabyLocalIter;
7898 5228 : if (bNegative)
7899 813 : nOutVal = -static_cast<OutType>(nVal);
7900 : else
7901 4415 : nOutVal = static_cast<OutType>(nVal);
7902 5228 : return true;
7903 : }
7904 2179 : nShift += 7;
7905 : // To avoid undefined behavior later when doing << nShift
7906 2179 : if (nShift >= static_cast<int>(sizeof(GIntBig)) * 8)
7907 : {
7908 0 : return false;
7909 : }
7910 : }
7911 : }
7912 :
7913 : /************************************************************************/
7914 : /* ReadUInt8() */
7915 : /************************************************************************/
7916 :
7917 1207 : inline bool ReadUInt8(const GByte *&pabyIter, const GByte *pabyEnd, GByte &nVal)
7918 : {
7919 1207 : if (pabyIter + sizeof(nVal) > pabyEnd)
7920 10 : return false;
7921 1197 : nVal = *pabyIter;
7922 1197 : pabyIter += sizeof(nVal);
7923 1197 : return true;
7924 : }
7925 :
7926 : /************************************************************************/
7927 : /* ReadFloat32() */
7928 : /************************************************************************/
7929 :
7930 239 : inline bool ReadFloat32(const GByte *&pabyIter, const GByte *pabyEnd,
7931 : float &fVal)
7932 : {
7933 239 : if (pabyIter + sizeof(fVal) > pabyEnd)
7934 8 : return false;
7935 : // cppcheck-suppress bufferAccessOutOfBounds
7936 231 : memcpy(&fVal, pabyIter, sizeof(fVal));
7937 231 : CPL_LSBPTR32(&fVal);
7938 231 : pabyIter += sizeof(fVal);
7939 231 : return true;
7940 : }
7941 :
7942 : /************************************************************************/
7943 : /* ReadFloat64() */
7944 : /************************************************************************/
7945 :
7946 541 : inline bool ReadFloat64(const GByte *&pabyIter, const GByte *pabyEnd,
7947 : double &dfVal)
7948 : {
7949 541 : if (pabyIter + sizeof(dfVal) > pabyEnd)
7950 22 : return false;
7951 519 : memcpy(&dfVal, pabyIter, sizeof(dfVal));
7952 519 : CPL_LSBPTR64(&dfVal);
7953 519 : pabyIter += sizeof(dfVal);
7954 519 : return true;
7955 : }
7956 :
7957 : } // namespace
7958 :
7959 : /************************************************************************/
7960 : /* OGRFeature::DeserializeFromBinary() */
7961 : /************************************************************************/
7962 :
7963 : /** Instantiate a feature from a binary encoding produces by SerializeToBinary()
7964 : *
7965 : * This sets the feature ID, attribute fields content and geometry fields
7966 : * content.
7967 : *
7968 : * DeserializeFromBinary() should be called on a feature whose feature definition
7969 : * is exactly the same as the one on which SerializeToBinary() was called.
7970 : * (but there is no security issue if not doing that, or if feeding a "random"
7971 : * buffer to that method).
7972 : *
7973 : * The format of that encoding may vary across GDAL versions.
7974 : *
7975 : * @since 3.9
7976 : */
7977 2861 : bool OGRFeature::DeserializeFromBinary(const GByte *pabyBuffer, size_t nSize)
7978 : {
7979 2861 : Reset();
7980 :
7981 2861 : const GByte *const pabyFlags = pabyBuffer;
7982 2861 : const GByte *const pabyEnd = pabyBuffer + nSize;
7983 2861 : const int nFieldCount = poDefn->GetFieldCount();
7984 2861 : const int nGeomFieldCount = poDefn->GetGeomFieldCount();
7985 2861 : const size_t nPresenceFlagsSize =
7986 2861 : ((2 * nFieldCount + nGeomFieldCount) + 7) / 8;
7987 2861 : if (nSize < nPresenceFlagsSize)
7988 12 : return false;
7989 2849 : pabyBuffer += nPresenceFlagsSize;
7990 :
7991 2849 : if (!ReadVarInt(pabyBuffer, pabyEnd, nFID))
7992 11 : return false;
7993 :
7994 12305 : const auto IsFlagBitSet = [pabyFlags](int iBit) -> bool
7995 12305 : { return (pabyFlags[iBit / 8] & (1 << (iBit % 8))) != 0; };
7996 :
7997 7530 : for (int i = 0; i < nFieldCount; ++i)
7998 : {
7999 4812 : OGRField &uField = pauFields[i];
8000 : {
8001 4812 : const int iBit = 2 * i;
8002 4812 : if (IsFlagBitSet(iBit))
8003 : {
8004 : // OGR_RawField_SetUnset(&uField);
8005 35 : continue;
8006 : }
8007 : }
8008 : {
8009 4777 : const int iBit = 2 * i + 1;
8010 4777 : if (IsFlagBitSet(iBit))
8011 : {
8012 1 : OGR_RawField_SetNull(&uField);
8013 1 : continue;
8014 : }
8015 : }
8016 4776 : const auto poFDefn = poDefn->GetFieldDefn(i);
8017 4776 : switch (poFDefn->GetType())
8018 : {
8019 2833 : case OFTInteger:
8020 : {
8021 2833 : uField.Set.nMarker2 = 0;
8022 2833 : uField.Set.nMarker3 = 0;
8023 2833 : if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Integer))
8024 2 : return false;
8025 2831 : break;
8026 : }
8027 227 : case OFTInteger64:
8028 : {
8029 227 : uField.Set.nMarker2 = 0;
8030 227 : uField.Set.nMarker3 = 0;
8031 227 : if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Integer64))
8032 7 : return false;
8033 220 : break;
8034 : }
8035 220 : case OFTReal:
8036 : {
8037 220 : uField.Set.nMarker2 = 0;
8038 220 : uField.Set.nMarker3 = 0;
8039 220 : if (!ReadFloat64(pabyBuffer, pabyEnd, uField.Real))
8040 8 : return false;
8041 212 : break;
8042 : }
8043 212 : case OFTString:
8044 : {
8045 212 : size_t nStrSize = 0;
8046 423 : if (!ReadVarUInt(pabyBuffer, pabyEnd, nStrSize) ||
8047 211 : nStrSize > std::numeric_limits<size_t>::max() - 1)
8048 : {
8049 9 : return false;
8050 : }
8051 211 : if (nStrSize > static_cast<size_t>(pabyEnd - pabyBuffer))
8052 8 : return false;
8053 : auto ptr =
8054 203 : static_cast<char *>(VSI_MALLOC_VERBOSE(nStrSize + 1));
8055 203 : if (!ptr)
8056 0 : return false;
8057 203 : uField.Set.nMarker2 = 0;
8058 203 : uField.Set.nMarker3 = 0;
8059 203 : uField.String = ptr;
8060 203 : memcpy(uField.String, pabyBuffer, nStrSize);
8061 203 : uField.String[nStrSize] = 0;
8062 203 : pabyBuffer += nStrSize;
8063 203 : break;
8064 : }
8065 196 : case OFTIntegerList:
8066 : {
8067 196 : int nCount = 0;
8068 388 : if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
8069 192 : nCount > pabyEnd - pabyBuffer)
8070 : {
8071 11 : return false;
8072 : }
8073 : auto ptr = static_cast<int *>(
8074 190 : VSI_MALLOC2_VERBOSE(nCount, sizeof(int)));
8075 190 : if (!ptr)
8076 3 : return false;
8077 187 : uField.Set.nMarker2 = 0;
8078 187 : uField.Set.nMarker3 = 0;
8079 187 : uField.IntegerList.paList = ptr;
8080 187 : uField.IntegerList.nCount = nCount;
8081 559 : for (int j = 0; j < nCount; ++j)
8082 : {
8083 374 : if (!ReadVarInt(pabyBuffer, pabyEnd,
8084 374 : uField.IntegerList.paList[j]))
8085 2 : return false;
8086 : }
8087 185 : break;
8088 : }
8089 185 : case OFTInteger64List:
8090 : {
8091 185 : int nCount = 0;
8092 368 : if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
8093 183 : nCount > pabyEnd - pabyBuffer)
8094 : {
8095 11 : return false;
8096 : }
8097 : auto ptr = static_cast<GIntBig *>(
8098 180 : VSI_MALLOC2_VERBOSE(nCount, sizeof(GIntBig)));
8099 180 : if (!ptr)
8100 0 : return false;
8101 180 : uField.Set.nMarker2 = 0;
8102 180 : uField.Set.nMarker3 = 0;
8103 180 : uField.Integer64List.paList = ptr;
8104 180 : uField.Integer64List.nCount = nCount;
8105 545 : for (int j = 0; j < nCount; ++j)
8106 : {
8107 371 : if (!ReadVarInt(pabyBuffer, pabyEnd,
8108 371 : uField.Integer64List.paList[j]))
8109 6 : return false;
8110 : }
8111 174 : break;
8112 : }
8113 174 : case OFTRealList:
8114 : {
8115 174 : int nCount = 0;
8116 343 : if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
8117 169 : nCount > pabyEnd - pabyBuffer)
8118 : {
8119 26 : return false;
8120 : }
8121 : auto ptr = static_cast<double *>(
8122 165 : VSI_MALLOC2_VERBOSE(nCount, sizeof(double)));
8123 165 : if (!ptr)
8124 3 : return false;
8125 162 : uField.Set.nMarker2 = 0;
8126 162 : uField.Set.nMarker3 = 0;
8127 162 : uField.RealList.paList = ptr;
8128 162 : uField.RealList.nCount = nCount;
8129 469 : for (int j = 0; j < nCount; ++j)
8130 : {
8131 321 : if (!ReadFloat64(pabyBuffer, pabyEnd,
8132 321 : uField.RealList.paList[j]))
8133 14 : return false;
8134 : }
8135 148 : break;
8136 : }
8137 148 : case OFTStringList:
8138 : {
8139 148 : int nCount = 0;
8140 295 : if (!ReadVarInt(pabyBuffer, pabyEnd, nCount) || nCount < 0 ||
8141 441 : nCount > std::numeric_limits<int>::max() - 1 ||
8142 146 : nCount > pabyEnd - pabyBuffer)
8143 : {
8144 17 : return false;
8145 : }
8146 : auto ptr = static_cast<char **>(
8147 143 : VSI_CALLOC_VERBOSE(nCount + 1, sizeof(char *)));
8148 143 : if (!ptr)
8149 0 : return false;
8150 143 : uField.Set.nMarker2 = 0;
8151 143 : uField.Set.nMarker3 = 0;
8152 143 : uField.StringList.paList = ptr;
8153 143 : uField.StringList.nCount = nCount;
8154 413 : for (int j = 0; j < nCount; ++j)
8155 : {
8156 282 : size_t nStrSize = 0;
8157 563 : if (!ReadVarUInt(pabyBuffer, pabyEnd, nStrSize) ||
8158 281 : nStrSize > std::numeric_limits<size_t>::max() - 1)
8159 : {
8160 12 : return false;
8161 : }
8162 281 : if (nStrSize > static_cast<size_t>(pabyEnd - pabyBuffer))
8163 11 : return false;
8164 540 : uField.StringList.paList[j] =
8165 270 : static_cast<char *>(VSI_MALLOC_VERBOSE(nStrSize + 1));
8166 270 : if (!uField.StringList.paList[j])
8167 0 : return false;
8168 270 : memcpy(uField.StringList.paList[j], pabyBuffer, nStrSize);
8169 270 : uField.StringList.paList[j][nStrSize] = 0;
8170 270 : pabyBuffer += nStrSize;
8171 : }
8172 131 : break;
8173 : }
8174 203 : case OFTBinary:
8175 : {
8176 203 : int nBinSize = 0;
8177 203 : if (!ReadVarInt(pabyBuffer, pabyEnd, nBinSize) || nBinSize < 0)
8178 : {
8179 7 : return false;
8180 : }
8181 199 : if (nBinSize > pabyEnd - pabyBuffer)
8182 3 : return false;
8183 196 : auto ptr = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nBinSize));
8184 196 : if (!ptr)
8185 0 : return false;
8186 196 : uField.Set.nMarker2 = 0;
8187 196 : uField.Set.nMarker3 = 0;
8188 196 : uField.Binary.paData = ptr;
8189 196 : uField.Binary.nCount = nBinSize;
8190 196 : memcpy(uField.Binary.paData, pabyBuffer, nBinSize);
8191 196 : pabyBuffer += nBinSize;
8192 196 : break;
8193 : }
8194 0 : case OFTWideString:
8195 : case OFTWideStringList:
8196 0 : break;
8197 131 : case OFTDate:
8198 : {
8199 131 : memset(&uField, 0, sizeof(uField));
8200 131 : if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Date.Year) ||
8201 259 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Month) ||
8202 128 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Day))
8203 : {
8204 4 : return false;
8205 : }
8206 127 : break;
8207 : }
8208 127 : case OFTTime:
8209 : {
8210 127 : memset(&uField, 0, sizeof(uField));
8211 127 : if (!ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Hour) ||
8212 126 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Minute) ||
8213 374 : !ReadFloat32(pabyBuffer, pabyEnd, uField.Date.Second) ||
8214 121 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.TZFlag))
8215 : {
8216 7 : return false;
8217 : }
8218 120 : break;
8219 : }
8220 120 : case OFTDateTime:
8221 : {
8222 120 : memset(&uField, 0, sizeof(uField));
8223 120 : if (!ReadVarInt(pabyBuffer, pabyEnd, uField.Date.Year) ||
8224 118 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Month) ||
8225 117 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Day) ||
8226 116 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Hour) ||
8227 115 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.Minute) ||
8228 348 : !ReadFloat32(pabyBuffer, pabyEnd, uField.Date.Second) ||
8229 110 : !ReadUInt8(pabyBuffer, pabyEnd, uField.Date.TZFlag))
8230 : {
8231 11 : return false;
8232 : }
8233 109 : break;
8234 : }
8235 : }
8236 : }
8237 5402 : for (int i = 0; i < nGeomFieldCount; ++i)
8238 : {
8239 2716 : const int iBit = 2 * nFieldCount + i;
8240 2716 : if (IsFlagBitSet(iBit))
8241 : {
8242 1013 : continue;
8243 : }
8244 1703 : size_t nWkbSize = 0;
8245 1703 : if (!ReadVarUInt(pabyBuffer, pabyEnd, nWkbSize))
8246 : {
8247 32 : return false;
8248 : }
8249 1702 : if (nWkbSize > static_cast<size_t>(pabyEnd - pabyBuffer))
8250 : {
8251 23 : return false;
8252 : }
8253 1679 : OGRGeometry *poGeom = nullptr;
8254 1679 : if (OGRGeometryFactory::createFromWkb(
8255 1679 : pabyBuffer, poDefn->GetGeomFieldDefn(i)->GetSpatialRef(),
8256 3350 : &poGeom, nWkbSize, wkbVariantIso) != OGRERR_NONE ||
8257 1671 : !poGeom)
8258 : {
8259 8 : delete poGeom;
8260 8 : return false;
8261 : }
8262 1671 : pabyBuffer += nWkbSize;
8263 1671 : papoGeometries[i] = poGeom;
8264 : }
8265 2686 : return true;
8266 : }
8267 :
8268 : /************************************************************************/
8269 : /* OGRFeature::ConstFieldIterator */
8270 : /************************************************************************/
8271 :
8272 : struct OGRFeature::FieldValue::Private
8273 : {
8274 : CPL_DISALLOW_COPY_ASSIGN(Private)
8275 :
8276 : OGRFeature *m_poSelf = nullptr;
8277 : int m_nPos = 0;
8278 : mutable std::vector<int> m_anList{};
8279 : mutable std::vector<GIntBig> m_anList64{};
8280 : mutable std::vector<double> m_adfList{};
8281 : mutable std::vector<std::string> m_aosList{};
8282 :
8283 4 : Private(const OGRFeature *poSelf, int iFieldIndex)
8284 4 : : m_poSelf(const_cast<OGRFeature *>(poSelf)), m_nPos(iFieldIndex)
8285 : {
8286 4 : }
8287 :
8288 47 : Private(OGRFeature *poSelf, int iFieldIndex)
8289 47 : : m_poSelf(poSelf), m_nPos(iFieldIndex)
8290 : {
8291 47 : }
8292 : };
8293 :
8294 : struct OGRFeature::ConstFieldIterator::Private
8295 : {
8296 : CPL_DISALLOW_COPY_ASSIGN(Private)
8297 :
8298 : OGRFeature::FieldValue m_oValue;
8299 : int m_nPos = 0;
8300 :
8301 4 : Private(const OGRFeature *poSelf, int iFieldIndex)
8302 4 : : m_oValue(poSelf, iFieldIndex)
8303 : {
8304 4 : }
8305 : };
8306 :
8307 : //! @cond Doxygen_Suppress
8308 4 : OGRFeature::ConstFieldIterator::ConstFieldIterator(const OGRFeature *poSelf,
8309 4 : int nPos)
8310 4 : : m_poPrivate(new Private(poSelf, nPos))
8311 : {
8312 4 : m_poPrivate->m_nPos = nPos;
8313 4 : }
8314 :
8315 : OGRFeature::ConstFieldIterator::~ConstFieldIterator() = default;
8316 :
8317 22 : const OGRFeature::FieldValue &OGRFeature::ConstFieldIterator::operator*() const
8318 : {
8319 22 : return m_poPrivate->m_oValue;
8320 : }
8321 :
8322 22 : OGRFeature::ConstFieldIterator &OGRFeature::ConstFieldIterator::operator++()
8323 : {
8324 22 : ++m_poPrivate->m_nPos;
8325 22 : m_poPrivate->m_oValue.m_poPrivate->m_nPos = m_poPrivate->m_nPos;
8326 22 : return *this;
8327 : }
8328 :
8329 24 : bool OGRFeature::ConstFieldIterator::operator!=(
8330 : const ConstFieldIterator &it) const
8331 : {
8332 24 : return m_poPrivate->m_nPos != it.m_poPrivate->m_nPos;
8333 : }
8334 :
8335 : //! @endcond
8336 :
8337 2 : OGRFeature::ConstFieldIterator OGRFeature::begin() const
8338 : {
8339 2 : return {this, 0};
8340 : }
8341 :
8342 2 : OGRFeature::ConstFieldIterator OGRFeature::end() const
8343 : {
8344 2 : return {this, GetFieldCount()};
8345 : }
8346 :
8347 : /************************************************************************/
8348 : /* OGRFeature::FieldValue */
8349 : /************************************************************************/
8350 :
8351 4 : OGRFeature::FieldValue::FieldValue(const OGRFeature *poFeature, int iFieldIndex)
8352 4 : : m_poPrivate(new Private(poFeature, iFieldIndex))
8353 : {
8354 4 : }
8355 :
8356 47 : OGRFeature::FieldValue::FieldValue(OGRFeature *poFeature, int iFieldIndex)
8357 47 : : m_poPrivate(new Private(poFeature, iFieldIndex))
8358 : {
8359 47 : }
8360 :
8361 14 : OGRFeature::FieldValue &OGRFeature::FieldValue::Assign(const FieldValue &oOther)
8362 : {
8363 27 : if (&oOther != this &&
8364 13 : !(m_poPrivate->m_poSelf == oOther.m_poPrivate->m_poSelf &&
8365 2 : m_poPrivate->m_nPos == oOther.m_poPrivate->m_nPos))
8366 : {
8367 12 : OGRFieldType eOtherType(oOther.GetType());
8368 12 : if (oOther.IsNull())
8369 1 : SetNull();
8370 11 : else if (oOther.IsUnset())
8371 1 : Unset();
8372 10 : else if (eOtherType == OFTInteger)
8373 2 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8374 : oOther.GetInteger());
8375 8 : else if (eOtherType == OFTInteger64)
8376 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8377 : oOther.GetInteger64());
8378 7 : else if (eOtherType == OFTReal)
8379 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8380 : oOther.GetDouble());
8381 6 : else if (eOtherType == OFTString)
8382 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8383 : oOther.GetString());
8384 5 : else if (eOtherType == OFTDate || eOtherType == OFTDateTime ||
8385 : eOtherType == OFTTime)
8386 : {
8387 1 : int nYear = 0;
8388 1 : int nMonth = 0;
8389 1 : int nDay = 0;
8390 1 : int nHour = 0;
8391 1 : int nMinute = 0;
8392 1 : float fSecond = 0.0f;
8393 1 : int nTZFlag = 0;
8394 1 : oOther.GetDateTime(&nYear, &nMonth, &nDay, &nHour, &nMinute,
8395 : &fSecond, &nTZFlag);
8396 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nYear, nMonth,
8397 : nDay, nHour, nMinute, fSecond,
8398 1 : nTZFlag);
8399 : }
8400 4 : else if (eOtherType == OFTStringList)
8401 : {
8402 2 : m_poPrivate->m_poSelf->SetField(
8403 1 : m_poPrivate->m_nPos,
8404 2 : oOther.m_poPrivate->m_poSelf->GetFieldAsStringList(
8405 1 : oOther.m_poPrivate->m_nPos));
8406 : }
8407 3 : else if (eOtherType == OFTIntegerList)
8408 : {
8409 1 : operator=(oOther.GetAsIntegerList());
8410 : }
8411 2 : else if (eOtherType == OFTInteger64List)
8412 : {
8413 1 : operator=(oOther.GetAsInteger64List());
8414 : }
8415 1 : else if (eOtherType == OFTRealList)
8416 : {
8417 1 : operator=(oOther.GetAsDoubleList());
8418 : }
8419 : }
8420 14 : return *this;
8421 : }
8422 :
8423 : OGRFeature::FieldValue &
8424 12 : OGRFeature::FieldValue::operator=(const FieldValue &oOther)
8425 : {
8426 12 : return Assign(oOther);
8427 : }
8428 :
8429 : //! @cond Doxygen_Suppress
8430 2 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(FieldValue &&oOther)
8431 : {
8432 2 : return Assign(oOther);
8433 : }
8434 :
8435 : //! @endcond
8436 :
8437 1 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(int nVal)
8438 : {
8439 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nVal);
8440 1 : return *this;
8441 : }
8442 :
8443 1 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(GIntBig nVal)
8444 : {
8445 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nVal);
8446 1 : return *this;
8447 : }
8448 :
8449 1 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(double dfVal)
8450 : {
8451 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, dfVal);
8452 1 : return *this;
8453 : }
8454 :
8455 2 : OGRFeature::FieldValue &OGRFeature::FieldValue::operator=(const char *pszVal)
8456 : {
8457 2 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, pszVal);
8458 2 : return *this;
8459 : }
8460 :
8461 : OGRFeature::FieldValue &
8462 1 : OGRFeature::FieldValue::operator=(const std::string &osVal)
8463 : {
8464 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, osVal.c_str());
8465 1 : return *this;
8466 : }
8467 :
8468 : OGRFeature::FieldValue &
8469 3 : OGRFeature::FieldValue::operator=(const std::vector<int> &oArray)
8470 : {
8471 9 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8472 3 : static_cast<int>(oArray.size()),
8473 5 : oArray.empty() ? nullptr : oArray.data());
8474 3 : return *this;
8475 : }
8476 :
8477 : OGRFeature::FieldValue &
8478 3 : OGRFeature::FieldValue::operator=(const std::vector<GIntBig> &oArray)
8479 : {
8480 9 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8481 3 : static_cast<int>(oArray.size()),
8482 5 : oArray.empty() ? nullptr : oArray.data());
8483 3 : return *this;
8484 : }
8485 :
8486 : OGRFeature::FieldValue &
8487 3 : OGRFeature::FieldValue::operator=(const std::vector<double> &oArray)
8488 : {
8489 9 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos,
8490 3 : static_cast<int>(oArray.size()),
8491 5 : oArray.empty() ? nullptr : oArray.data());
8492 3 : return *this;
8493 : }
8494 :
8495 : OGRFeature::FieldValue &
8496 2 : OGRFeature::FieldValue::operator=(const std::vector<std::string> &oArray)
8497 : {
8498 2 : CPLStringList aosList;
8499 4 : for (auto &&oStr : oArray)
8500 2 : aosList.AddString(oStr.c_str());
8501 2 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, aosList.List());
8502 4 : return *this;
8503 : }
8504 :
8505 : OGRFeature::FieldValue &
8506 2 : OGRFeature::FieldValue::operator=(CSLConstList papszValues)
8507 : {
8508 2 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, papszValues);
8509 2 : return *this;
8510 : }
8511 :
8512 1 : void OGRFeature::FieldValue::SetDateTime(int nYear, int nMonth, int nDay,
8513 : int nHour, int nMinute, float fSecond,
8514 : int nTZFlag)
8515 : {
8516 1 : m_poPrivate->m_poSelf->SetField(m_poPrivate->m_nPos, nYear, nMonth, nDay,
8517 : nHour, nMinute, fSecond, nTZFlag);
8518 1 : }
8519 :
8520 2 : void OGRFeature::FieldValue::SetNull()
8521 : {
8522 2 : m_poPrivate->m_poSelf->SetFieldNull(m_poPrivate->m_nPos);
8523 2 : }
8524 :
8525 3 : void OGRFeature::FieldValue::clear()
8526 : {
8527 3 : m_poPrivate->m_poSelf->UnsetField(m_poPrivate->m_nPos);
8528 3 : }
8529 :
8530 : //! @cond Doxygen_Suppress
8531 : OGRFeature::FieldValue::~FieldValue() = default;
8532 :
8533 : //! @endcond
8534 :
8535 188 : int OGRFeature::FieldValue::GetIndex() const
8536 : {
8537 188 : return m_poPrivate->m_nPos;
8538 : }
8539 :
8540 89 : const OGRFieldDefn *OGRFeature::FieldValue::GetDefn() const
8541 : {
8542 89 : return m_poPrivate->m_poSelf->GetFieldDefnRef(GetIndex());
8543 : }
8544 :
8545 48 : const OGRField *OGRFeature::FieldValue::GetRawValue() const
8546 : {
8547 48 : return &(m_poPrivate->m_poSelf->pauFields[GetIndex()]);
8548 : }
8549 :
8550 15 : bool OGRFeature::FieldValue::IsUnset() const
8551 : {
8552 15 : return CPL_TO_BOOL(OGR_RawField_IsUnset(GetRawValue()));
8553 : }
8554 :
8555 15 : bool OGRFeature::FieldValue::IsNull() const
8556 : {
8557 15 : return CPL_TO_BOOL(OGR_RawField_IsNull(GetRawValue()));
8558 : }
8559 :
8560 5 : int OGRFeature::FieldValue::GetAsInteger() const
8561 : {
8562 5 : return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8563 5 : ->GetFieldAsInteger(GetIndex());
8564 : }
8565 :
8566 4 : GIntBig OGRFeature::FieldValue::GetAsInteger64() const
8567 : {
8568 4 : return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8569 4 : ->GetFieldAsInteger64(GetIndex());
8570 : }
8571 :
8572 4 : double OGRFeature::FieldValue::GetAsDouble() const
8573 : {
8574 4 : return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8575 4 : ->GetFieldAsDouble(GetIndex());
8576 : }
8577 :
8578 5 : const char *OGRFeature::FieldValue::GetAsString() const
8579 : {
8580 5 : return const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8581 5 : ->GetFieldAsString(GetIndex());
8582 : }
8583 :
8584 2 : bool OGRFeature::FieldValue::GetDateTime(int *pnYear, int *pnMonth, int *pnDay,
8585 : int *pnHour, int *pnMinute,
8586 : float *pfSecond, int *pnTZFlag) const
8587 : {
8588 2 : return CPL_TO_BOOL(const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8589 : ->GetFieldAsDateTime(GetIndex(), pnYear, pnMonth,
8590 : pnDay, pnHour, pnMinute,
8591 2 : pfSecond, pnTZFlag));
8592 : }
8593 :
8594 2 : const std::vector<int> &OGRFeature::FieldValue::GetAsIntegerList() const
8595 : {
8596 2 : int nCount = 0;
8597 2 : auto &&panList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8598 2 : ->GetFieldAsIntegerList(GetIndex(), &nCount);
8599 2 : m_poPrivate->m_anList.assign(panList, panList + nCount);
8600 2 : return m_poPrivate->m_anList;
8601 : }
8602 :
8603 2 : const std::vector<GIntBig> &OGRFeature::FieldValue::GetAsInteger64List() const
8604 : {
8605 2 : int nCount = 0;
8606 2 : auto &&panList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8607 2 : ->GetFieldAsInteger64List(GetIndex(), &nCount);
8608 2 : m_poPrivate->m_anList64.assign(panList, panList + nCount);
8609 2 : return m_poPrivate->m_anList64;
8610 : }
8611 :
8612 2 : const std::vector<double> &OGRFeature::FieldValue::GetAsDoubleList() const
8613 : {
8614 2 : int nCount = 0;
8615 2 : auto &&panList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8616 2 : ->GetFieldAsDoubleList(GetIndex(), &nCount);
8617 2 : m_poPrivate->m_adfList.assign(panList, panList + nCount);
8618 2 : return m_poPrivate->m_adfList;
8619 : }
8620 :
8621 1 : const std::vector<std::string> &OGRFeature::FieldValue::GetAsStringList() const
8622 : {
8623 1 : auto &&papszList = const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8624 1 : ->GetFieldAsStringList(GetIndex());
8625 1 : m_poPrivate->m_aosList.clear();
8626 1 : if (papszList)
8627 : {
8628 3 : for (char **papszIter = papszList; *papszIter; ++papszIter)
8629 : {
8630 2 : m_poPrivate->m_aosList.emplace_back(*papszIter);
8631 : }
8632 : }
8633 1 : return m_poPrivate->m_aosList;
8634 : }
8635 :
8636 2 : OGRFeature::FieldValue::operator CSLConstList() const
8637 : {
8638 : return const_cast<CSLConstList>(
8639 2 : const_cast<OGRFeature *>(m_poPrivate->m_poSelf)
8640 2 : ->GetFieldAsStringList(GetIndex()));
8641 : }
8642 :
8643 16 : OGRRangeFieldDomain *OGRRangeFieldDomain::Clone() const
8644 : {
8645 : auto poDomain = new OGRRangeFieldDomain(
8646 16 : m_osName, m_osDescription, m_eFieldType, m_eFieldSubType, m_sMin,
8647 16 : m_bMinIsInclusive, m_sMax, m_bMaxIsInclusive);
8648 16 : poDomain->SetMergePolicy(m_eMergePolicy);
8649 16 : poDomain->SetSplitPolicy(m_eSplitPolicy);
8650 16 : return poDomain;
8651 : }
8652 :
8653 15 : OGRGlobFieldDomain *OGRGlobFieldDomain::Clone() const
8654 : {
8655 : auto poDomain = new OGRGlobFieldDomain(
8656 15 : m_osName, m_osDescription, m_eFieldType, m_eFieldSubType, m_osGlob);
8657 15 : poDomain->SetMergePolicy(m_eMergePolicy);
8658 15 : poDomain->SetSplitPolicy(m_eSplitPolicy);
8659 15 : return poDomain;
8660 : }
8661 : #if defined(__GNUC__)
8662 : #pragma GCC diagnostic pop
8663 : #endif
|