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 547 : OGRGeoJSONLayer::OGRGeoJSONLayer(const char *pszName,
48 : OGRSpatialReference *poSRSIn,
49 : OGRwkbGeometryType eGType,
50 : OGRGeoJSONDataSource *poDS,
51 547 : OGRGeoJSONReader *poReader)
52 : : OGRMemLayer(pszName, poSRSIn, eGType), poDS_(poDS), poReader_(poReader),
53 : bHasAppendedFeatures_(false), bOriginalIdModified_(false),
54 547 : nTotalFeatureCount_(0)
55 : {
56 547 : SetAdvertizeUTF8(true);
57 547 : SetUpdatable(poDS->IsUpdatable());
58 547 : }
59 :
60 : /************************************************************************/
61 : /* ~OGRGeoJSONLayer */
62 : /************************************************************************/
63 :
64 1094 : OGRGeoJSONLayer::~OGRGeoJSONLayer()
65 : {
66 547 : TerminateAppendSession();
67 547 : delete poReader_;
68 1094 : }
69 :
70 : /************************************************************************/
71 : /* TerminateAppendSession() */
72 : /************************************************************************/
73 :
74 1112 : void OGRGeoJSONLayer::TerminateAppendSession()
75 : {
76 1112 : 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 1112 : }
91 :
92 : /************************************************************************/
93 : /* GetFIDColumn */
94 : /************************************************************************/
95 :
96 1609 : const char *OGRGeoJSONLayer::GetFIDColumn() const
97 : {
98 1609 : return sFIDColumn_.c_str();
99 : }
100 :
101 : /************************************************************************/
102 : /* SetFIDColumn */
103 : /************************************************************************/
104 :
105 53 : void OGRGeoJSONLayer::SetFIDColumn(const char *pszFIDColumn)
106 : {
107 53 : sFIDColumn_ = pszFIDColumn;
108 53 : }
109 :
110 : /************************************************************************/
111 : /* ResetReading() */
112 : /************************************************************************/
113 :
114 1438 : void OGRGeoJSONLayer::ResetReading()
115 : {
116 1438 : nFeatureReadSinceReset_ = 0;
117 1438 : if (poReader_)
118 : {
119 548 : TerminateAppendSession();
120 548 : poReader_->ResetReading();
121 : }
122 : else
123 890 : OGRMemLayer::ResetReading();
124 1438 : }
125 :
126 : /************************************************************************/
127 : /* GetNextFeature() */
128 : /************************************************************************/
129 :
130 1913 : OGRFeature *OGRGeoJSONLayer::GetNextFeature()
131 : {
132 1913 : if (poReader_)
133 : {
134 1143 : if (bHasAppendedFeatures_)
135 : {
136 1 : ResetReading();
137 : }
138 : while (true)
139 : {
140 1245 : OGRFeature *poFeature = poReader_->GetNextFeature(this);
141 1245 : if (poFeature == nullptr)
142 177 : return nullptr;
143 2245 : if ((m_poFilterGeom == nullptr ||
144 109 : FilterGeometry(
145 2136 : poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
146 1040 : (m_poAttrQuery == nullptr ||
147 151 : m_poAttrQuery->Evaluate(poFeature)))
148 : {
149 966 : nFeatureReadSinceReset_++;
150 966 : return poFeature;
151 : }
152 102 : delete poFeature;
153 102 : }
154 : }
155 : else
156 : {
157 770 : auto ret = OGRMemLayer::GetNextFeature();
158 770 : if (ret)
159 : {
160 493 : nFeatureReadSinceReset_++;
161 : }
162 770 : return ret;
163 : }
164 : }
165 :
166 : /************************************************************************/
167 : /* GetFeatureCount() */
168 : /************************************************************************/
169 :
170 731 : GIntBig OGRGeoJSONLayer::GetFeatureCount(int bForce)
171 : {
172 731 : if (poReader_)
173 : {
174 387 : if (m_poFilterGeom == nullptr && m_poAttrQuery == nullptr &&
175 379 : nTotalFeatureCount_ >= 0)
176 : {
177 379 : return nTotalFeatureCount_;
178 : }
179 8 : return OGRLayer::GetFeatureCount(bForce);
180 : }
181 : else
182 : {
183 344 : return OGRMemLayer::GetFeatureCount(bForce);
184 : }
185 : }
186 :
187 : /************************************************************************/
188 : /* GetFeature() */
189 : /************************************************************************/
190 :
191 399 : OGRFeature *OGRGeoJSONLayer::GetFeature(GIntBig nFID)
192 : {
193 399 : 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 372 : 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 366 : bool OGRGeoJSONLayer::SetOrUpdateFeaturePreparation()
236 : {
237 366 : if (!IsUpdatable())
238 1 : return false;
239 365 : if (poReader_)
240 : {
241 10 : auto nNextIndex = nFeatureReadSinceReset_;
242 10 : if (!IngestAll())
243 0 : return false;
244 10 : SetNextByIndex(nNextIndex);
245 : }
246 365 : return true;
247 : }
248 :
249 : /************************************************************************/
250 : /* ISetFeature() */
251 : /************************************************************************/
252 :
253 360 : OGRErr OGRGeoJSONLayer::ISetFeature(OGRFeature *poFeature)
254 : {
255 360 : if (!SetOrUpdateFeaturePreparation())
256 1 : return OGRERR_FAILURE;
257 359 : 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 :
366 287 : const char *pszJson = json_object_to_json_string_ext(
367 : poObj, JSON_C_TO_STRING_PLAIN
368 : #ifdef JSON_C_TO_STRING_NOSLASHESCAPE
369 : | JSON_C_TO_STRING_NOSLASHESCAPE
370 : #endif
371 : );
372 :
373 287 : VSIFPrintfL(fp, "%s", pszJson);
374 287 : json_object_put(poObj);
375 :
376 287 : if (poFeature->GetFID() == OGRNullFID)
377 : {
378 287 : poFeature->SetFID(nTotalFeatureCount_);
379 : }
380 287 : nTotalFeatureCount_++;
381 :
382 287 : return OGRERR_NONE;
383 : }
384 3 : else if (IngestAll())
385 : {
386 3 : break;
387 : }
388 : else
389 : {
390 0 : return OGRERR_FAILURE;
391 : }
392 1 : }
393 : }
394 4 : return OGRMemLayer::ICreateFeature(poFeature);
395 : }
396 :
397 : /************************************************************************/
398 : /* DeleteFeature() */
399 : /************************************************************************/
400 :
401 5 : OGRErr OGRGeoJSONLayer::DeleteFeature(GIntBig nFID)
402 : {
403 5 : if (!IsUpdatable() || !IngestAll())
404 2 : return OGRERR_FAILURE;
405 3 : return OGRMemLayer::DeleteFeature(nFID);
406 : }
407 :
408 : /************************************************************************/
409 : /* CreateField() */
410 : /************************************************************************/
411 :
412 0 : OGRErr OGRGeoJSONLayer::CreateField(const OGRFieldDefn *poField, int bApproxOK)
413 : {
414 0 : if (!IsUpdatable() || !IngestAll())
415 0 : return OGRERR_FAILURE;
416 0 : return OGRMemLayer::CreateField(poField, bApproxOK);
417 : }
418 :
419 : /************************************************************************/
420 : /* DeleteField() */
421 : /************************************************************************/
422 :
423 0 : OGRErr OGRGeoJSONLayer::DeleteField(int iField)
424 : {
425 0 : if (!IsUpdatable() || !IngestAll())
426 0 : return OGRERR_FAILURE;
427 0 : return OGRMemLayer::DeleteField(iField);
428 : }
429 :
430 : /************************************************************************/
431 : /* ReorderFields() */
432 : /************************************************************************/
433 :
434 0 : OGRErr OGRGeoJSONLayer::ReorderFields(int *panMap)
435 : {
436 0 : if (!IsUpdatable() || !IngestAll())
437 0 : return OGRERR_FAILURE;
438 0 : return OGRMemLayer::ReorderFields(panMap);
439 : }
440 :
441 : /************************************************************************/
442 : /* AlterFieldDefn() */
443 : /************************************************************************/
444 :
445 0 : OGRErr OGRGeoJSONLayer::AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
446 : int nFlagsIn)
447 : {
448 0 : if (!IsUpdatable() || !IngestAll())
449 0 : return OGRERR_FAILURE;
450 0 : return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
451 : }
452 :
453 : /************************************************************************/
454 : /* CreateGeomField() */
455 : /************************************************************************/
456 :
457 0 : OGRErr OGRGeoJSONLayer::CreateGeomField(const OGRGeomFieldDefn *poGeomField,
458 : int bApproxOK)
459 : {
460 0 : if (!IsUpdatable() || !IngestAll())
461 0 : return OGRERR_FAILURE;
462 0 : return OGRMemLayer::CreateGeomField(poGeomField, bApproxOK);
463 : }
464 :
465 48 : OGRErr OGRGeoJSONLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
466 : bool bForce)
467 : {
468 48 : if (iGeomField != 0)
469 : {
470 0 : return OGRERR_FAILURE;
471 : }
472 :
473 69 : if (poReader_ && poReader_->ExtentRead() &&
474 21 : TestCapability(OLCFastGetExtent))
475 : {
476 19 : *psExtent = poReader_->GetExtent3D();
477 19 : return OGRERR_NONE;
478 : }
479 : else
480 : {
481 29 : return OGRMemLayer::IGetExtent(iGeomField, psExtent, bForce);
482 : }
483 : }
484 :
485 11 : OGRErr OGRGeoJSONLayer::IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
486 : bool bForce)
487 : {
488 :
489 11 : if (iGeomField != 0)
490 : {
491 0 : return OGRERR_FAILURE;
492 : }
493 :
494 22 : if (poReader_ && poReader_->ExtentRead() &&
495 11 : TestCapability(OLCFastGetExtent3D))
496 : {
497 9 : *psExtent3D = poReader_->GetExtent3D();
498 9 : return OGRERR_NONE;
499 : }
500 : else
501 : {
502 2 : return OGRMemLayer::IGetExtent3D(iGeomField, psExtent3D, bForce);
503 : }
504 : }
505 :
506 : /************************************************************************/
507 : /* TestCapability() */
508 : /************************************************************************/
509 :
510 649 : int OGRGeoJSONLayer::TestCapability(const char *pszCap) const
511 :
512 : {
513 649 : if (EQUAL(pszCap, OLCCurveGeometries))
514 220 : return FALSE;
515 429 : else if (EQUAL(pszCap, OLCMeasuredGeometries))
516 220 : return m_bSupportsMGeometries;
517 209 : else if (EQUAL(pszCap, OLCZGeometries))
518 6 : return m_bSupportsZGeometries;
519 203 : else if (EQUAL(pszCap, OLCStringsAsUTF8))
520 31 : return TRUE;
521 172 : else if (EQUAL(pszCap, OLCFastGetExtent) ||
522 145 : EQUAL(pszCap, OLCFastGetExtent3D))
523 42 : return m_poFilterGeom == nullptr && m_poAttrQuery == nullptr;
524 130 : return OGRMemLayer::TestCapability(pszCap);
525 : }
526 :
527 : /************************************************************************/
528 : /* SyncToDisk() */
529 : /************************************************************************/
530 :
531 3 : OGRErr OGRGeoJSONLayer::SyncToDisk()
532 : {
533 3 : TerminateAppendSession();
534 :
535 3 : poDS_->FlushCache(false);
536 3 : return OGRERR_NONE;
537 : }
538 :
539 : /************************************************************************/
540 : /* AddFeature */
541 : /************************************************************************/
542 :
543 344 : void OGRGeoJSONLayer::AddFeature(OGRFeature *poFeature)
544 : {
545 344 : GIntBig nFID = poFeature->GetFID();
546 :
547 : // Detect potential FID duplicates and make sure they are eventually
548 : // unique.
549 344 : if (-1 == nFID)
550 : {
551 278 : nFID = GetFeatureCount(FALSE);
552 278 : OGRFeature *poTryFeature = nullptr;
553 278 : while ((poTryFeature = GetFeature(nFID)) != nullptr)
554 : {
555 0 : nFID++;
556 0 : delete poTryFeature;
557 : }
558 : }
559 : else
560 : {
561 66 : OGRFeature *poTryFeature = nullptr;
562 66 : if ((poTryFeature = GetFeature(nFID)) != nullptr)
563 : {
564 3 : if (!bOriginalIdModified_)
565 : {
566 2 : CPLError(
567 : CE_Warning, CPLE_AppDefined,
568 : "Several features with id = " CPL_FRMT_GIB " have been "
569 : "found. Altering it to be unique. This warning will not "
570 : "be emitted anymore for this layer",
571 : nFID);
572 2 : bOriginalIdModified_ = true;
573 : }
574 3 : delete poTryFeature;
575 3 : nFID = GetFeatureCount(FALSE);
576 5 : while ((poTryFeature = GetFeature(nFID)) != nullptr)
577 : {
578 2 : nFID++;
579 2 : delete poTryFeature;
580 : }
581 : }
582 : }
583 344 : poFeature->SetFID(nFID);
584 :
585 344 : if (!CPL_INT64_FITS_ON_INT32(nFID))
586 2 : SetMetadataItem(OLMD_FID64, "YES");
587 :
588 344 : const bool bIsUpdatable = IsUpdatable();
589 344 : SetUpdatable(true); // Temporary toggle on updatable flag.
590 344 : CPL_IGNORE_RET_VAL(OGRMemLayer::SetFeature(poFeature));
591 344 : SetUpdatable(bIsUpdatable);
592 344 : SetUpdated(false);
593 344 : }
594 :
595 : /************************************************************************/
596 : /* DetectGeometryType */
597 : /************************************************************************/
598 :
599 228 : void OGRGeoJSONLayer::DetectGeometryType()
600 : {
601 228 : auto poFDefn = GetLayerDefn();
602 228 : if (poFDefn->GetGeomType() != wkbUnknown)
603 75 : return;
604 :
605 153 : ResetReading();
606 153 : bool bFirstGeometry = true;
607 153 : OGRwkbGeometryType eLayerGeomType = wkbUnknown;
608 306 : for (const auto &poFeature : *this)
609 : {
610 153 : const OGRGeometry *poGeometry = poFeature->GetGeometryRef();
611 153 : if (nullptr != poGeometry)
612 : {
613 89 : OGRwkbGeometryType eGeomType = poGeometry->getGeometryType();
614 89 : if (!OGRGeoJSONUpdateLayerGeomType(bFirstGeometry, eGeomType,
615 : eLayerGeomType))
616 : {
617 4 : break;
618 : }
619 : }
620 : }
621 :
622 : {
623 306 : auto oTemporaryUnsealer(poFDefn->GetTemporaryUnsealer());
624 153 : poFDefn->SetGeomType(eLayerGeomType);
625 : }
626 :
627 153 : ResetReading();
628 : }
629 :
630 : /************************************************************************/
631 : /* GetDataset() */
632 : /************************************************************************/
633 :
634 2 : GDALDataset *OGRGeoJSONLayer::GetDataset()
635 : {
636 2 : return poDS_;
637 : }
|