LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/geojson - ogrgeojsonlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 207 240 86.2 %
Date: 2024-05-03 15:49:35 Functions: 22 27 81.5 %

          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             : }

Generated by: LCOV version 1.14