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 465 : OGRGeoJSONLayer::OGRGeoJSONLayer(const char *pszName,
48 : OGRSpatialReference *poSRSIn,
49 : OGRwkbGeometryType eGType,
50 : OGRGeoJSONDataSource *poDS,
51 465 : OGRGeoJSONReader *poReader)
52 : : OGRMemLayer(pszName, poSRSIn, eGType), poDS_(poDS), poReader_(poReader),
53 : bHasAppendedFeatures_(false), bOriginalIdModified_(false),
54 465 : nTotalFeatureCount_(0)
55 : {
56 465 : SetAdvertizeUTF8(true);
57 465 : SetUpdatable(poDS->IsUpdatable());
58 465 : }
59 :
60 : /************************************************************************/
61 : /* ~OGRGeoJSONLayer */
62 : /************************************************************************/
63 :
64 930 : OGRGeoJSONLayer::~OGRGeoJSONLayer()
65 : {
66 465 : TerminateAppendSession();
67 465 : delete poReader_;
68 930 : }
69 :
70 : /************************************************************************/
71 : /* TerminateAppendSession() */
72 : /************************************************************************/
73 :
74 1006 : void OGRGeoJSONLayer::TerminateAppendSession()
75 : {
76 1006 : 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 1006 : }
91 :
92 : /************************************************************************/
93 : /* GetFIDColumn */
94 : /************************************************************************/
95 :
96 1524 : const char *OGRGeoJSONLayer::GetFIDColumn()
97 : {
98 1524 : 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 1306 : void OGRGeoJSONLayer::ResetReading()
115 : {
116 1306 : nFeatureReadSinceReset_ = 0;
117 1306 : if (poReader_)
118 : {
119 524 : TerminateAppendSession();
120 524 : poReader_->ResetReading();
121 : }
122 : else
123 782 : OGRMemLayer::ResetReading();
124 1306 : }
125 :
126 : /************************************************************************/
127 : /* GetNextFeature() */
128 : /************************************************************************/
129 :
130 1825 : OGRFeature *OGRGeoJSONLayer::GetNextFeature()
131 : {
132 1825 : if (poReader_)
133 : {
134 1117 : if (bHasAppendedFeatures_)
135 : {
136 1 : ResetReading();
137 : }
138 : while (true)
139 : {
140 1219 : OGRFeature *poFeature = poReader_->GetNextFeature(this);
141 1219 : if (poFeature == nullptr)
142 173 : return nullptr;
143 2201 : if ((m_poFilterGeom == nullptr ||
144 109 : FilterGeometry(
145 2092 : poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
146 1018 : (m_poAttrQuery == nullptr ||
147 151 : m_poAttrQuery->Evaluate(poFeature)))
148 : {
149 944 : nFeatureReadSinceReset_++;
150 944 : return poFeature;
151 : }
152 102 : delete poFeature;
153 102 : }
154 : }
155 : else
156 : {
157 708 : auto ret = OGRMemLayer::GetNextFeature();
158 708 : if (ret)
159 : {
160 453 : nFeatureReadSinceReset_++;
161 : }
162 708 : return ret;
163 : }
164 : }
165 :
166 : /************************************************************************/
167 : /* GetFeatureCount() */
168 : /************************************************************************/
169 :
170 674 : GIntBig OGRGeoJSONLayer::GetFeatureCount(int bForce)
171 : {
172 674 : if (poReader_)
173 : {
174 364 : if (m_poFilterGeom == nullptr && m_poAttrQuery == nullptr &&
175 356 : nTotalFeatureCount_ >= 0)
176 : {
177 356 : return nTotalFeatureCount_;
178 : }
179 8 : return OGRLayer::GetFeatureCount(bForce);
180 : }
181 : else
182 : {
183 310 : return OGRMemLayer::GetFeatureCount(bForce);
184 : }
185 : }
186 :
187 : /************************************************************************/
188 : /* GetFeature() */
189 : /************************************************************************/
190 :
191 367 : OGRFeature *OGRGeoJSONLayer::GetFeature(GIntBig nFID)
192 : {
193 367 : 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 340 : 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 334 : bool OGRGeoJSONLayer::SetOrUpdateFeaturePreparation()
236 : {
237 334 : if (!IsUpdatable())
238 1 : return false;
239 333 : if (poReader_)
240 : {
241 10 : auto nNextIndex = nFeatureReadSinceReset_;
242 10 : if (!IngestAll())
243 0 : return false;
244 10 : SetNextByIndex(nNextIndex);
245 : }
246 333 : return true;
247 : }
248 :
249 : /************************************************************************/
250 : /* ISetFeature() */
251 : /************************************************************************/
252 :
253 328 : OGRErr OGRGeoJSONLayer::ISetFeature(OGRFeature *poFeature)
254 : {
255 328 : if (!SetOrUpdateFeaturePreparation())
256 1 : return OGRERR_FAILURE;
257 327 : 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 5 : OGRErr OGRGeoJSONLayer::GetExtent(OGREnvelope *psExtent, int bForce)
458 : {
459 5 : return GetExtent(0, psExtent, bForce);
460 : }
461 :
462 48 : OGRErr OGRGeoJSONLayer::GetExtent(int iGeomField, OGREnvelope *psExtent,
463 : int bForce)
464 : {
465 48 : if (iGeomField != 0)
466 : {
467 4 : return OGRERR_FAILURE;
468 : }
469 :
470 61 : if (poReader_ && poReader_->ExtentRead() &&
471 17 : TestCapability(OLCFastGetExtent))
472 : {
473 15 : *psExtent = poReader_->GetExtent3D();
474 15 : return OGRERR_NONE;
475 : }
476 : else
477 : {
478 29 : return OGRMemLayer::GetExtentInternal(iGeomField, psExtent, bForce);
479 : }
480 : }
481 :
482 11 : OGRErr OGRGeoJSONLayer::GetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
483 : int bForce)
484 : {
485 :
486 11 : if (iGeomField != 0)
487 : {
488 0 : return OGRERR_FAILURE;
489 : }
490 :
491 22 : if (poReader_ && poReader_->ExtentRead() &&
492 11 : TestCapability(OLCFastGetExtent3D))
493 : {
494 9 : *psExtent3D = poReader_->GetExtent3D();
495 9 : return OGRERR_NONE;
496 : }
497 : else
498 : {
499 2 : return OGRMemLayer::GetExtent3D(iGeomField, psExtent3D, bForce);
500 : }
501 : }
502 :
503 : /************************************************************************/
504 : /* TestCapability() */
505 : /************************************************************************/
506 :
507 561 : int OGRGeoJSONLayer::TestCapability(const char *pszCap)
508 :
509 : {
510 561 : if (EQUAL(pszCap, OLCCurveGeometries))
511 188 : return FALSE;
512 373 : else if (EQUAL(pszCap, OLCZGeometries))
513 6 : return TRUE;
514 367 : else if (EQUAL(pszCap, OLCStringsAsUTF8))
515 24 : return TRUE;
516 343 : else if (EQUAL(pszCap, OLCFastGetExtent) ||
517 320 : EQUAL(pszCap, OLCFastGetExtent3D))
518 38 : return m_poFilterGeom == nullptr && m_poAttrQuery == nullptr;
519 305 : return OGRMemLayer::TestCapability(pszCap);
520 : }
521 :
522 : /************************************************************************/
523 : /* SyncToDisk() */
524 : /************************************************************************/
525 :
526 3 : OGRErr OGRGeoJSONLayer::SyncToDisk()
527 : {
528 3 : TerminateAppendSession();
529 :
530 3 : poDS_->FlushCache(false);
531 3 : return OGRERR_NONE;
532 : }
533 :
534 : /************************************************************************/
535 : /* AddFeature */
536 : /************************************************************************/
537 :
538 312 : void OGRGeoJSONLayer::AddFeature(OGRFeature *poFeature)
539 : {
540 312 : GIntBig nFID = poFeature->GetFID();
541 :
542 : // Detect potential FID duplicates and make sure they are eventually
543 : // unique.
544 312 : if (-1 == nFID)
545 : {
546 253 : nFID = GetFeatureCount(FALSE);
547 253 : OGRFeature *poTryFeature = nullptr;
548 253 : while ((poTryFeature = GetFeature(nFID)) != nullptr)
549 : {
550 0 : nFID++;
551 0 : delete poTryFeature;
552 : }
553 : }
554 : else
555 : {
556 59 : OGRFeature *poTryFeature = nullptr;
557 59 : if ((poTryFeature = GetFeature(nFID)) != nullptr)
558 : {
559 3 : if (!bOriginalIdModified_)
560 : {
561 2 : CPLError(
562 : CE_Warning, CPLE_AppDefined,
563 : "Several features with id = " CPL_FRMT_GIB " have been "
564 : "found. Altering it to be unique. This warning will not "
565 : "be emitted anymore for this layer",
566 : nFID);
567 2 : bOriginalIdModified_ = true;
568 : }
569 3 : delete poTryFeature;
570 3 : nFID = GetFeatureCount(FALSE);
571 5 : while ((poTryFeature = GetFeature(nFID)) != nullptr)
572 : {
573 2 : nFID++;
574 2 : delete poTryFeature;
575 : }
576 : }
577 : }
578 312 : poFeature->SetFID(nFID);
579 :
580 312 : if (!CPL_INT64_FITS_ON_INT32(nFID))
581 2 : SetMetadataItem(OLMD_FID64, "YES");
582 :
583 312 : const bool bIsUpdatable = IsUpdatable();
584 312 : SetUpdatable(true); // Temporary toggle on updatable flag.
585 312 : CPL_IGNORE_RET_VAL(OGRMemLayer::SetFeature(poFeature));
586 312 : SetUpdatable(bIsUpdatable);
587 312 : SetUpdated(false);
588 312 : }
589 :
590 : /************************************************************************/
591 : /* DetectGeometryType */
592 : /************************************************************************/
593 :
594 195 : void OGRGeoJSONLayer::DetectGeometryType()
595 : {
596 195 : if (GetLayerDefn()->GetGeomType() != wkbUnknown)
597 59 : return;
598 :
599 136 : ResetReading();
600 136 : bool bFirstGeometry = true;
601 136 : OGRwkbGeometryType eLayerGeomType = wkbUnknown;
602 273 : for (const auto &poFeature : *this)
603 : {
604 137 : const OGRGeometry *poGeometry = poFeature->GetGeometryRef();
605 137 : if (nullptr != poGeometry)
606 : {
607 80 : OGRwkbGeometryType eGeomType = poGeometry->getGeometryType();
608 80 : if (!OGRGeoJSONUpdateLayerGeomType(bFirstGeometry, eGeomType,
609 : eLayerGeomType))
610 : {
611 4 : break;
612 : }
613 : }
614 : }
615 :
616 : {
617 136 : auto poFDefn = GetLayerDefn();
618 272 : auto oTemporaryUnsealer(poFDefn->GetTemporaryUnsealer());
619 136 : poFDefn->SetGeomType(eLayerGeomType);
620 : }
621 :
622 136 : ResetReading();
623 : }
624 :
625 : /************************************************************************/
626 : /* GetDataset() */
627 : /************************************************************************/
628 :
629 1 : GDALDataset *OGRGeoJSONLayer::GetDataset()
630 : {
631 1 : return poDS_;
632 : }
|