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