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 541 : OGRGeoJSONLayer::OGRGeoJSONLayer(const char *pszName,
48 : OGRSpatialReference *poSRSIn,
49 : OGRwkbGeometryType eGType,
50 : OGRGeoJSONDataSource *poDS,
51 541 : OGRGeoJSONReader *poReader)
52 : : OGRMemLayer(pszName, poSRSIn, eGType), poDS_(poDS), poReader_(poReader),
53 : bHasAppendedFeatures_(false), bOriginalIdModified_(false),
54 541 : nTotalFeatureCount_(0)
55 : {
56 541 : SetAdvertizeUTF8(true);
57 541 : SetUpdatable(poDS->IsUpdatable());
58 541 : }
59 :
60 : /************************************************************************/
61 : /* ~OGRGeoJSONLayer */
62 : /************************************************************************/
63 :
64 1082 : OGRGeoJSONLayer::~OGRGeoJSONLayer()
65 : {
66 541 : TerminateAppendSession();
67 541 : delete poReader_;
68 1082 : }
69 :
70 : /************************************************************************/
71 : /* TerminateAppendSession() */
72 : /************************************************************************/
73 :
74 1101 : void OGRGeoJSONLayer::TerminateAppendSession()
75 : {
76 1101 : 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 1101 : }
91 :
92 : /************************************************************************/
93 : /* GetFIDColumn */
94 : /************************************************************************/
95 :
96 1581 : const char *OGRGeoJSONLayer::GetFIDColumn()
97 : {
98 1581 : 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 1430 : void OGRGeoJSONLayer::ResetReading()
115 : {
116 1430 : nFeatureReadSinceReset_ = 0;
117 1430 : if (poReader_)
118 : {
119 543 : TerminateAppendSession();
120 543 : poReader_->ResetReading();
121 : }
122 : else
123 887 : OGRMemLayer::ResetReading();
124 1430 : }
125 :
126 : /************************************************************************/
127 : /* GetNextFeature() */
128 : /************************************************************************/
129 :
130 1887 : OGRFeature *OGRGeoJSONLayer::GetNextFeature()
131 : {
132 1887 : 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 756 : auto ret = OGRMemLayer::GetNextFeature();
158 756 : if (ret)
159 : {
160 482 : nFeatureReadSinceReset_++;
161 : }
162 756 : return ret;
163 : }
164 : }
165 :
166 : /************************************************************************/
167 : /* GetFeatureCount() */
168 : /************************************************************************/
169 :
170 727 : GIntBig OGRGeoJSONLayer::GetFeatureCount(int bForce)
171 : {
172 727 : if (poReader_)
173 : {
174 385 : if (m_poFilterGeom == nullptr && m_poAttrQuery == nullptr &&
175 377 : nTotalFeatureCount_ >= 0)
176 : {
177 377 : return nTotalFeatureCount_;
178 : }
179 8 : return OGRLayer::GetFeatureCount(bForce);
180 : }
181 : else
182 : {
183 342 : return OGRMemLayer::GetFeatureCount(bForce);
184 : }
185 : }
186 :
187 : /************************************************************************/
188 : /* GetFeature() */
189 : /************************************************************************/
190 :
191 398 : OGRFeature *OGRGeoJSONLayer::GetFeature(GIntBig nFID)
192 : {
193 398 : 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 371 : 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 365 : bool OGRGeoJSONLayer::SetOrUpdateFeaturePreparation()
236 : {
237 365 : if (!IsUpdatable())
238 1 : return false;
239 364 : if (poReader_)
240 : {
241 10 : auto nNextIndex = nFeatureReadSinceReset_;
242 10 : if (!IngestAll())
243 0 : return false;
244 10 : SetNextByIndex(nNextIndex);
245 : }
246 364 : return true;
247 : }
248 :
249 : /************************************************************************/
250 : /* ISetFeature() */
251 : /************************************************************************/
252 :
253 359 : OGRErr OGRGeoJSONLayer::ISetFeature(OGRFeature *poFeature)
254 : {
255 359 : if (!SetOrUpdateFeaturePreparation())
256 1 : return OGRERR_FAILURE;
257 358 : 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 647 : int OGRGeoJSONLayer::TestCapability(const char *pszCap)
503 :
504 : {
505 647 : if (EQUAL(pszCap, OLCCurveGeometries))
506 219 : return FALSE;
507 428 : else if (EQUAL(pszCap, OLCMeasuredGeometries))
508 219 : return m_bSupportsMGeometries;
509 209 : else if (EQUAL(pszCap, OLCZGeometries))
510 6 : return m_bSupportsZGeometries;
511 203 : else if (EQUAL(pszCap, OLCStringsAsUTF8))
512 31 : return TRUE;
513 172 : else if (EQUAL(pszCap, OLCFastGetExtent) ||
514 141 : EQUAL(pszCap, OLCFastGetExtent3D))
515 46 : return m_poFilterGeom == nullptr && m_poAttrQuery == nullptr;
516 126 : return OGRMemLayer::TestCapability(pszCap);
517 : }
518 :
519 : /************************************************************************/
520 : /* SyncToDisk() */
521 : /************************************************************************/
522 :
523 3 : OGRErr OGRGeoJSONLayer::SyncToDisk()
524 : {
525 3 : TerminateAppendSession();
526 :
527 3 : poDS_->FlushCache(false);
528 3 : return OGRERR_NONE;
529 : }
530 :
531 : /************************************************************************/
532 : /* AddFeature */
533 : /************************************************************************/
534 :
535 343 : void OGRGeoJSONLayer::AddFeature(OGRFeature *poFeature)
536 : {
537 343 : GIntBig nFID = poFeature->GetFID();
538 :
539 : // Detect potential FID duplicates and make sure they are eventually
540 : // unique.
541 343 : if (-1 == nFID)
542 : {
543 277 : nFID = GetFeatureCount(FALSE);
544 277 : OGRFeature *poTryFeature = nullptr;
545 277 : while ((poTryFeature = GetFeature(nFID)) != nullptr)
546 : {
547 0 : nFID++;
548 0 : delete poTryFeature;
549 : }
550 : }
551 : else
552 : {
553 66 : OGRFeature *poTryFeature = nullptr;
554 66 : if ((poTryFeature = GetFeature(nFID)) != nullptr)
555 : {
556 3 : if (!bOriginalIdModified_)
557 : {
558 2 : CPLError(
559 : CE_Warning, CPLE_AppDefined,
560 : "Several features with id = " CPL_FRMT_GIB " have been "
561 : "found. Altering it to be unique. This warning will not "
562 : "be emitted anymore for this layer",
563 : nFID);
564 2 : bOriginalIdModified_ = true;
565 : }
566 3 : delete poTryFeature;
567 3 : nFID = GetFeatureCount(FALSE);
568 5 : while ((poTryFeature = GetFeature(nFID)) != nullptr)
569 : {
570 2 : nFID++;
571 2 : delete poTryFeature;
572 : }
573 : }
574 : }
575 343 : poFeature->SetFID(nFID);
576 :
577 343 : if (!CPL_INT64_FITS_ON_INT32(nFID))
578 2 : SetMetadataItem(OLMD_FID64, "YES");
579 :
580 343 : const bool bIsUpdatable = IsUpdatable();
581 343 : SetUpdatable(true); // Temporary toggle on updatable flag.
582 343 : CPL_IGNORE_RET_VAL(OGRMemLayer::SetFeature(poFeature));
583 343 : SetUpdatable(bIsUpdatable);
584 343 : SetUpdated(false);
585 343 : }
586 :
587 : /************************************************************************/
588 : /* DetectGeometryType */
589 : /************************************************************************/
590 :
591 227 : void OGRGeoJSONLayer::DetectGeometryType()
592 : {
593 227 : if (GetLayerDefn()->GetGeomType() != wkbUnknown)
594 74 : return;
595 :
596 153 : ResetReading();
597 153 : bool bFirstGeometry = true;
598 153 : OGRwkbGeometryType eLayerGeomType = wkbUnknown;
599 306 : for (const auto &poFeature : *this)
600 : {
601 153 : const OGRGeometry *poGeometry = poFeature->GetGeometryRef();
602 153 : if (nullptr != poGeometry)
603 : {
604 89 : OGRwkbGeometryType eGeomType = poGeometry->getGeometryType();
605 89 : if (!OGRGeoJSONUpdateLayerGeomType(bFirstGeometry, eGeomType,
606 : eLayerGeomType))
607 : {
608 4 : break;
609 : }
610 : }
611 : }
612 :
613 : {
614 153 : auto poFDefn = GetLayerDefn();
615 306 : auto oTemporaryUnsealer(poFDefn->GetTemporaryUnsealer());
616 153 : poFDefn->SetGeomType(eLayerGeomType);
617 : }
618 :
619 153 : ResetReading();
620 : }
621 :
622 : /************************************************************************/
623 : /* GetDataset() */
624 : /************************************************************************/
625 :
626 1 : GDALDataset *OGRGeoJSONLayer::GetDataset()
627 : {
628 1 : return poDS_;
629 : }
|