Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implementation of OGRGeoJSONLayer class (OGR GeoJSON Driver).
5 : * Author: Mateusz Loskot, mateusz@loskot.net
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2007, Mateusz Loskot
9 : * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include <algorithm>
15 :
16 : #if !DEBUG_JSON
17 : #ifdef __clang__
18 : #pragma clang diagnostic push
19 : #pragma clang diagnostic ignored "-Wunknown-pragmas"
20 : #pragma clang diagnostic ignored "-Wdocumentation"
21 : #pragma clang diagnostic ignored "-Wold-style-cast"
22 : #endif
23 : #endif // !DEBUG_VERBOSE
24 :
25 : #include <json.h>
26 :
27 : #if !DEBUG_JSON
28 : #ifdef __clang
29 : #pragma clang diagnostic pop
30 : #endif
31 : #endif // !DEBUG_VERBOSE
32 :
33 : #include "ogr_geojson.h"
34 : #include "ogrgeojsonreader.h"
35 :
36 : /************************************************************************/
37 : /* STATIC MEMBERS DEFINITION */
38 : /************************************************************************/
39 :
40 : const char *const OGRGeoJSONLayer::DefaultName = "OGRGeoJSON";
41 : const OGRwkbGeometryType OGRGeoJSONLayer::DefaultGeometryType = wkbUnknown;
42 :
43 : /************************************************************************/
44 : /* OGRGeoJSONLayer */
45 : /************************************************************************/
46 :
47 488 : OGRGeoJSONLayer::OGRGeoJSONLayer(const char *pszName,
48 : OGRSpatialReference *poSRSIn,
49 : OGRwkbGeometryType eGType,
50 : OGRGeoJSONDataSource *poDS,
51 488 : OGRGeoJSONReader *poReader)
52 : : OGRMemLayer(pszName, poSRSIn, eGType), poDS_(poDS), poReader_(poReader),
53 : bHasAppendedFeatures_(false), bOriginalIdModified_(false),
54 488 : nTotalFeatureCount_(0)
55 : {
56 488 : SetAdvertizeUTF8(true);
57 488 : SetUpdatable(poDS->IsUpdatable());
58 488 : }
59 :
60 : /************************************************************************/
61 : /* ~OGRGeoJSONLayer */
62 : /************************************************************************/
63 :
64 976 : OGRGeoJSONLayer::~OGRGeoJSONLayer()
65 : {
66 488 : TerminateAppendSession();
67 488 : delete poReader_;
68 976 : }
69 :
70 : /************************************************************************/
71 : /* TerminateAppendSession() */
72 : /************************************************************************/
73 :
74 1047 : void OGRGeoJSONLayer::TerminateAppendSession()
75 : {
76 1047 : if (bHasAppendedFeatures_)
77 : {
78 : #if defined(__GNUC__)
79 : #pragma GCC diagnostic push
80 : #pragma GCC diagnostic ignored "-Wnull-dereference"
81 : #endif
82 6 : VSILFILE *fp = poReader_->GetFP();
83 : #if defined(__GNUC__)
84 : #pragma GCC diagnostic pop
85 : #endif
86 6 : VSIFPrintfL(fp, "\n]\n}\n");
87 6 : VSIFFlushL(fp);
88 6 : bHasAppendedFeatures_ = false;
89 : }
90 1047 : }
91 :
92 : /************************************************************************/
93 : /* GetFIDColumn */
94 : /************************************************************************/
95 :
96 1562 : const char *OGRGeoJSONLayer::GetFIDColumn()
97 : {
98 1562 : return sFIDColumn_.c_str();
99 : }
100 :
101 : /************************************************************************/
102 : /* SetFIDColumn */
103 : /************************************************************************/
104 :
105 46 : void OGRGeoJSONLayer::SetFIDColumn(const char *pszFIDColumn)
106 : {
107 46 : sFIDColumn_ = pszFIDColumn;
108 46 : }
109 :
110 : /************************************************************************/
111 : /* ResetReading() */
112 : /************************************************************************/
113 :
114 1336 : void OGRGeoJSONLayer::ResetReading()
115 : {
116 1336 : nFeatureReadSinceReset_ = 0;
117 1336 : if (poReader_)
118 : {
119 542 : TerminateAppendSession();
120 542 : poReader_->ResetReading();
121 : }
122 : else
123 794 : OGRMemLayer::ResetReading();
124 1336 : }
125 :
126 : /************************************************************************/
127 : /* GetNextFeature() */
128 : /************************************************************************/
129 :
130 1845 : OGRFeature *OGRGeoJSONLayer::GetNextFeature()
131 : {
132 1845 : if (poReader_)
133 : {
134 1131 : if (bHasAppendedFeatures_)
135 : {
136 1 : ResetReading();
137 : }
138 : while (true)
139 : {
140 1233 : OGRFeature *poFeature = poReader_->GetNextFeature(this);
141 1233 : if (poFeature == nullptr)
142 173 : return nullptr;
143 2229 : if ((m_poFilterGeom == nullptr ||
144 109 : FilterGeometry(
145 2120 : poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
146 1032 : (m_poAttrQuery == nullptr ||
147 151 : m_poAttrQuery->Evaluate(poFeature)))
148 : {
149 958 : nFeatureReadSinceReset_++;
150 958 : return poFeature;
151 : }
152 102 : delete poFeature;
153 102 : }
154 : }
155 : else
156 : {
157 714 : auto ret = OGRMemLayer::GetNextFeature();
158 714 : if (ret)
159 : {
160 458 : nFeatureReadSinceReset_++;
161 : }
162 714 : return ret;
163 : }
164 : }
165 :
166 : /************************************************************************/
167 : /* GetFeatureCount() */
168 : /************************************************************************/
169 :
170 705 : GIntBig OGRGeoJSONLayer::GetFeatureCount(int bForce)
171 : {
172 705 : if (poReader_)
173 : {
174 384 : if (m_poFilterGeom == nullptr && m_poAttrQuery == nullptr &&
175 376 : nTotalFeatureCount_ >= 0)
176 : {
177 376 : return nTotalFeatureCount_;
178 : }
179 8 : return OGRLayer::GetFeatureCount(bForce);
180 : }
181 : else
182 : {
183 321 : return OGRMemLayer::GetFeatureCount(bForce);
184 : }
185 : }
186 :
187 : /************************************************************************/
188 : /* GetFeature() */
189 : /************************************************************************/
190 :
191 375 : OGRFeature *OGRGeoJSONLayer::GetFeature(GIntBig nFID)
192 : {
193 375 : if (poReader_)
194 : {
195 27 : if (!IsUpdatable())
196 : {
197 22 : return poReader_->GetFeature(this, nFID);
198 : }
199 5 : return OGRLayer::GetFeature(nFID);
200 : }
201 : else
202 : {
203 348 : return OGRMemLayer::GetFeature(nFID);
204 : }
205 : }
206 :
207 : /************************************************************************/
208 : /* IngestAll() */
209 : /************************************************************************/
210 :
211 16 : bool OGRGeoJSONLayer::IngestAll()
212 : {
213 16 : if (poReader_)
214 : {
215 14 : TerminateAppendSession();
216 :
217 14 : OGRGeoJSONReader *poReader = poReader_;
218 14 : poReader_ = nullptr;
219 :
220 14 : nTotalFeatureCount_ = -1;
221 14 : bool bRet = poReader->IngestAll(this);
222 14 : delete poReader;
223 14 : return bRet;
224 : }
225 : else
226 : {
227 2 : return true;
228 : }
229 : }
230 :
231 : /************************************************************************/
232 : /* SetOrUpdateFeaturePreparation() */
233 : /************************************************************************/
234 :
235 342 : bool OGRGeoJSONLayer::SetOrUpdateFeaturePreparation()
236 : {
237 342 : if (!IsUpdatable())
238 1 : return false;
239 341 : if (poReader_)
240 : {
241 10 : auto nNextIndex = nFeatureReadSinceReset_;
242 10 : if (!IngestAll())
243 0 : return false;
244 10 : SetNextByIndex(nNextIndex);
245 : }
246 341 : return true;
247 : }
248 :
249 : /************************************************************************/
250 : /* ISetFeature() */
251 : /************************************************************************/
252 :
253 336 : OGRErr OGRGeoJSONLayer::ISetFeature(OGRFeature *poFeature)
254 : {
255 336 : if (!SetOrUpdateFeaturePreparation())
256 1 : return OGRERR_FAILURE;
257 335 : return OGRMemLayer::ISetFeature(poFeature);
258 : }
259 :
260 : /************************************************************************/
261 : /* IUpdateFeature() */
262 : /************************************************************************/
263 :
264 6 : OGRErr OGRGeoJSONLayer::IUpdateFeature(OGRFeature *poFeature,
265 : int nUpdatedFieldsCount,
266 : const int *panUpdatedFieldsIdx,
267 : int nUpdatedGeomFieldsCount,
268 : const int *panUpdatedGeomFieldsIdx,
269 : bool bUpdateStyleString)
270 : {
271 6 : if (!SetOrUpdateFeaturePreparation())
272 0 : return OGRERR_FAILURE;
273 6 : return OGRMemLayer::IUpdateFeature(
274 : poFeature, nUpdatedFieldsCount, panUpdatedFieldsIdx,
275 6 : nUpdatedGeomFieldsCount, panUpdatedGeomFieldsIdx, bUpdateStyleString);
276 : }
277 :
278 : /************************************************************************/
279 : /* ICreateFeature() */
280 : /************************************************************************/
281 :
282 291 : OGRErr OGRGeoJSONLayer::ICreateFeature(OGRFeature *poFeature)
283 : {
284 291 : if (!IsUpdatable())
285 0 : return OGRERR_FAILURE;
286 291 : if (poReader_)
287 : {
288 290 : bool bTryEasyAppend = true;
289 : while (true)
290 : {
291 : // We can trivially append to end of existing file, provided the
292 : // following conditions are met:
293 : // * the "features" array member is the last one of the main
294 : // object (poReader_->CanEasilyAppend())
295 : // * there is no "bbox" at feature collection level (could possibly
296 : // be supported)
297 : // * the features have no explicit FID field, so it is trivial to
298 : // derive the FID of newly created features without collision
299 : // * we know the total number of existing features
300 290 : if (bTryEasyAppend && poReader_->CanEasilyAppend() &&
301 289 : !poReader_->FCHasBBOX() && sFIDColumn_.empty() &&
302 869 : GetLayerDefn()->GetFieldIndex("id") < 0 &&
303 288 : nTotalFeatureCount_ >= 0)
304 : {
305 288 : VSILFILE *fp = poReader_->GetFP();
306 288 : if (!bHasAppendedFeatures_)
307 : {
308 : // Locate "} ] }" (or "[ ] }") pattern at end of file
309 7 : VSIFSeekL(fp, 0, SEEK_END);
310 7 : vsi_l_offset nOffset = VSIFTellL(fp);
311 7 : nOffset -= 10;
312 7 : VSIFSeekL(fp, nOffset, SEEK_SET);
313 : char szBuffer[11];
314 7 : VSIFReadL(szBuffer, 10, 1, fp);
315 7 : szBuffer[10] = 0;
316 7 : int i = 9;
317 : // Locate final }
318 11 : while (isspace(static_cast<unsigned char>(szBuffer[i])) &&
319 : i > 0)
320 4 : i--;
321 7 : if (szBuffer[i] != '}')
322 : {
323 0 : bTryEasyAppend = false;
324 0 : continue;
325 : }
326 7 : if (i > 0)
327 7 : i--;
328 : // Locate ']' ending features array
329 12 : while (isspace(static_cast<unsigned char>(szBuffer[i])) &&
330 : i > 0)
331 5 : i--;
332 7 : if (szBuffer[i] != ']')
333 : {
334 0 : bTryEasyAppend = false;
335 0 : continue;
336 : }
337 7 : if (i > 0)
338 7 : i--;
339 13 : while (isspace(static_cast<unsigned char>(szBuffer[i])) &&
340 : i > 0)
341 6 : i--;
342 : // Locate '}' ending last feature, or '[' starting features
343 : // array
344 7 : if (szBuffer[i] != '}' && szBuffer[i] != '[')
345 : {
346 1 : bTryEasyAppend = false;
347 1 : continue;
348 : }
349 6 : bool bExistingFeature = szBuffer[i] == '}';
350 6 : nOffset += i + 1;
351 6 : VSIFSeekL(fp, nOffset, SEEK_SET);
352 6 : if (bExistingFeature)
353 : {
354 5 : VSIFPrintfL(fp, ",");
355 : }
356 6 : VSIFPrintfL(fp, "\n");
357 6 : bHasAppendedFeatures_ = true;
358 : }
359 : else
360 : {
361 281 : VSIFPrintfL(fp, ",\n");
362 : }
363 : json_object *poObj =
364 287 : OGRGeoJSONWriteFeature(poFeature, oWriteOptions_);
365 287 : VSIFPrintfL(fp, "%s", json_object_to_json_string(poObj));
366 287 : json_object_put(poObj);
367 :
368 287 : if (poFeature->GetFID() == OGRNullFID)
369 : {
370 287 : poFeature->SetFID(nTotalFeatureCount_);
371 : }
372 287 : nTotalFeatureCount_++;
373 :
374 287 : return OGRERR_NONE;
375 : }
376 3 : else if (IngestAll())
377 : {
378 3 : break;
379 : }
380 : else
381 : {
382 0 : return OGRERR_FAILURE;
383 : }
384 1 : }
385 : }
386 4 : return OGRMemLayer::ICreateFeature(poFeature);
387 : }
388 :
389 : /************************************************************************/
390 : /* DeleteFeature() */
391 : /************************************************************************/
392 :
393 5 : OGRErr OGRGeoJSONLayer::DeleteFeature(GIntBig nFID)
394 : {
395 5 : if (!IsUpdatable() || !IngestAll())
396 2 : return OGRERR_FAILURE;
397 3 : return OGRMemLayer::DeleteFeature(nFID);
398 : }
399 :
400 : /************************************************************************/
401 : /* CreateField() */
402 : /************************************************************************/
403 :
404 0 : OGRErr OGRGeoJSONLayer::CreateField(const OGRFieldDefn *poField, int bApproxOK)
405 : {
406 0 : if (!IsUpdatable() || !IngestAll())
407 0 : return OGRERR_FAILURE;
408 0 : return OGRMemLayer::CreateField(poField, bApproxOK);
409 : }
410 :
411 : /************************************************************************/
412 : /* DeleteField() */
413 : /************************************************************************/
414 :
415 0 : OGRErr OGRGeoJSONLayer::DeleteField(int iField)
416 : {
417 0 : if (!IsUpdatable() || !IngestAll())
418 0 : return OGRERR_FAILURE;
419 0 : return OGRMemLayer::DeleteField(iField);
420 : }
421 :
422 : /************************************************************************/
423 : /* ReorderFields() */
424 : /************************************************************************/
425 :
426 0 : OGRErr OGRGeoJSONLayer::ReorderFields(int *panMap)
427 : {
428 0 : if (!IsUpdatable() || !IngestAll())
429 0 : return OGRERR_FAILURE;
430 0 : return OGRMemLayer::ReorderFields(panMap);
431 : }
432 :
433 : /************************************************************************/
434 : /* AlterFieldDefn() */
435 : /************************************************************************/
436 :
437 0 : OGRErr OGRGeoJSONLayer::AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
438 : int nFlagsIn)
439 : {
440 0 : if (!IsUpdatable() || !IngestAll())
441 0 : return OGRERR_FAILURE;
442 0 : return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
443 : }
444 :
445 : /************************************************************************/
446 : /* CreateGeomField() */
447 : /************************************************************************/
448 :
449 0 : OGRErr OGRGeoJSONLayer::CreateGeomField(const OGRGeomFieldDefn *poGeomField,
450 : int bApproxOK)
451 : {
452 0 : if (!IsUpdatable() || !IngestAll())
453 0 : return OGRERR_FAILURE;
454 0 : return OGRMemLayer::CreateGeomField(poGeomField, bApproxOK);
455 : }
456 :
457 52 : OGRErr OGRGeoJSONLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
458 : bool bForce)
459 : {
460 52 : if (iGeomField != 0)
461 : {
462 0 : return OGRERR_FAILURE;
463 : }
464 :
465 77 : if (poReader_ && poReader_->ExtentRead() &&
466 25 : TestCapability(OLCFastGetExtent))
467 : {
468 23 : *psExtent = poReader_->GetExtent3D();
469 23 : return OGRERR_NONE;
470 : }
471 : else
472 : {
473 29 : return OGRMemLayer::IGetExtent(iGeomField, psExtent, bForce);
474 : }
475 : }
476 :
477 11 : OGRErr OGRGeoJSONLayer::IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
478 : bool bForce)
479 : {
480 :
481 11 : if (iGeomField != 0)
482 : {
483 0 : return OGRERR_FAILURE;
484 : }
485 :
486 22 : if (poReader_ && poReader_->ExtentRead() &&
487 11 : TestCapability(OLCFastGetExtent3D))
488 : {
489 9 : *psExtent3D = poReader_->GetExtent3D();
490 9 : return OGRERR_NONE;
491 : }
492 : else
493 : {
494 2 : return OGRMemLayer::IGetExtent3D(iGeomField, psExtent3D, bForce);
495 : }
496 : }
497 :
498 : /************************************************************************/
499 : /* TestCapability() */
500 : /************************************************************************/
501 :
502 585 : int OGRGeoJSONLayer::TestCapability(const char *pszCap)
503 :
504 : {
505 585 : if (EQUAL(pszCap, OLCCurveGeometries))
506 196 : return FALSE;
507 389 : else if (EQUAL(pszCap, OLCZGeometries))
508 6 : return TRUE;
509 383 : else if (EQUAL(pszCap, OLCStringsAsUTF8))
510 24 : return TRUE;
511 359 : else if (EQUAL(pszCap, OLCFastGetExtent) ||
512 328 : EQUAL(pszCap, OLCFastGetExtent3D))
513 46 : return m_poFilterGeom == nullptr && m_poAttrQuery == nullptr;
514 313 : return OGRMemLayer::TestCapability(pszCap);
515 : }
516 :
517 : /************************************************************************/
518 : /* SyncToDisk() */
519 : /************************************************************************/
520 :
521 3 : OGRErr OGRGeoJSONLayer::SyncToDisk()
522 : {
523 3 : TerminateAppendSession();
524 :
525 3 : poDS_->FlushCache(false);
526 3 : return OGRERR_NONE;
527 : }
528 :
529 : /************************************************************************/
530 : /* AddFeature */
531 : /************************************************************************/
532 :
533 320 : void OGRGeoJSONLayer::AddFeature(OGRFeature *poFeature)
534 : {
535 320 : GIntBig nFID = poFeature->GetFID();
536 :
537 : // Detect potential FID duplicates and make sure they are eventually
538 : // unique.
539 320 : if (-1 == nFID)
540 : {
541 261 : nFID = GetFeatureCount(FALSE);
542 261 : OGRFeature *poTryFeature = nullptr;
543 261 : while ((poTryFeature = GetFeature(nFID)) != nullptr)
544 : {
545 0 : nFID++;
546 0 : delete poTryFeature;
547 : }
548 : }
549 : else
550 : {
551 59 : OGRFeature *poTryFeature = nullptr;
552 59 : if ((poTryFeature = GetFeature(nFID)) != nullptr)
553 : {
554 3 : if (!bOriginalIdModified_)
555 : {
556 2 : CPLError(
557 : CE_Warning, CPLE_AppDefined,
558 : "Several features with id = " CPL_FRMT_GIB " have been "
559 : "found. Altering it to be unique. This warning will not "
560 : "be emitted anymore for this layer",
561 : nFID);
562 2 : bOriginalIdModified_ = true;
563 : }
564 3 : delete poTryFeature;
565 3 : nFID = GetFeatureCount(FALSE);
566 5 : while ((poTryFeature = GetFeature(nFID)) != nullptr)
567 : {
568 2 : nFID++;
569 2 : delete poTryFeature;
570 : }
571 : }
572 : }
573 320 : poFeature->SetFID(nFID);
574 :
575 320 : if (!CPL_INT64_FITS_ON_INT32(nFID))
576 2 : SetMetadataItem(OLMD_FID64, "YES");
577 :
578 320 : const bool bIsUpdatable = IsUpdatable();
579 320 : SetUpdatable(true); // Temporary toggle on updatable flag.
580 320 : CPL_IGNORE_RET_VAL(OGRMemLayer::SetFeature(poFeature));
581 320 : SetUpdatable(bIsUpdatable);
582 320 : SetUpdated(false);
583 320 : }
584 :
585 : /************************************************************************/
586 : /* DetectGeometryType */
587 : /************************************************************************/
588 :
589 204 : void OGRGeoJSONLayer::DetectGeometryType()
590 : {
591 204 : if (GetLayerDefn()->GetGeomType() != wkbUnknown)
592 67 : return;
593 :
594 137 : ResetReading();
595 137 : bool bFirstGeometry = true;
596 137 : OGRwkbGeometryType eLayerGeomType = wkbUnknown;
597 274 : for (const auto &poFeature : *this)
598 : {
599 137 : const OGRGeometry *poGeometry = poFeature->GetGeometryRef();
600 137 : if (nullptr != poGeometry)
601 : {
602 80 : OGRwkbGeometryType eGeomType = poGeometry->getGeometryType();
603 80 : if (!OGRGeoJSONUpdateLayerGeomType(bFirstGeometry, eGeomType,
604 : eLayerGeomType))
605 : {
606 4 : break;
607 : }
608 : }
609 : }
610 :
611 : {
612 137 : auto poFDefn = GetLayerDefn();
613 274 : auto oTemporaryUnsealer(poFDefn->GetTemporaryUnsealer());
614 137 : poFDefn->SetGeomType(eLayerGeomType);
615 : }
616 :
617 137 : ResetReading();
618 : }
619 :
620 : /************************************************************************/
621 : /* GetDataset() */
622 : /************************************************************************/
623 :
624 1 : GDALDataset *OGRGeoJSONLayer::GetDataset()
625 : {
626 1 : return poDS_;
627 : }
|