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