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