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