LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/jsonfg - ogr_jsonfg.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 49 55 89.1 %
Date: 2025-10-01 17:07:58 Functions: 29 31 93.5 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implementation of OGC Features and Geometries JSON (JSON-FG)
       5             :  * Author:   Even Rouault <even.rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2023, Even Rouault <even.rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #ifndef OGR_JSONFG_H_INCLUDED
      14             : #define OGR_JSONFG_H_INCLUDED
      15             : 
      16             : #include "cpl_vsi_virtual.h"
      17             : 
      18             : #include "gdal_priv.h"
      19             : #include "ogrsf_frmts.h"
      20             : #include "ogrgeojsonutils.h"
      21             : #include "ogrgeojsonwriter.h"
      22             : #include "ogrjsoncollectionstreamingparser.h"
      23             : #include "memdataset.h"
      24             : #include "directedacyclicgraph.hpp"
      25             : 
      26             : #include <map>
      27             : #include <set>
      28             : #include <utility>
      29             : 
      30             : /************************************************************************/
      31             : /*                         OGRJSONFGMemLayer                            */
      32             : /************************************************************************/
      33             : 
      34             : /** Layer with all features ingested into memory. */
      35         152 : class OGRJSONFGMemLayer final : public OGRMemLayer
      36             : {
      37             :   public:
      38             :     OGRJSONFGMemLayer(GDALDataset *poDS, const char *pszName,
      39             :                       OGRSpatialReference *poSRS, OGRwkbGeometryType eGType);
      40             :     ~OGRJSONFGMemLayer() override;
      41             : 
      42           3 :     const char *GetFIDColumn() const override
      43             :     {
      44           3 :         return osFIDColumn_.c_str();
      45             :     }
      46             : 
      47           0 :     void SetFIDColumn(const char *pszName)
      48             :     {
      49           0 :         osFIDColumn_ = pszName;
      50           0 :     }
      51             : 
      52             :     void AddFeature(std::unique_ptr<OGRFeature> poFeature);
      53             : 
      54          23 :     GDALDataset *GetDataset() override
      55             :     {
      56          23 :         return m_poDS;
      57             :     }
      58             : 
      59             :   private:
      60             :     GDALDataset *m_poDS = nullptr;
      61             :     std::string osFIDColumn_{};
      62             :     bool bOriginalIdModified_ = false;
      63             : 
      64             :     CPL_DISALLOW_COPY_ASSIGN(OGRJSONFGMemLayer)
      65             : };
      66             : 
      67             : /************************************************************************/
      68             : /*                    OGRJSONFGStreamedLayer                            */
      69             : /************************************************************************/
      70             : 
      71             : class OGRJSONFGStreamingParser;
      72             : 
      73             : /** Layer with features being acquired progressively through a streaming
      74             :  parser.
      75             : 
      76             :  Only applies for FeatureCollection read through a file
      77             : */
      78             : class OGRJSONFGStreamedLayer final
      79             :     : public OGRLayer,
      80             :       public OGRGetNextFeatureThroughRaw<OGRJSONFGStreamedLayer>
      81             : {
      82             :   public:
      83             :     OGRJSONFGStreamedLayer(GDALDataset *poDS, const char *pszName,
      84             :                            OGRSpatialReference *poSRS,
      85             :                            OGRwkbGeometryType eGType);
      86             :     ~OGRJSONFGStreamedLayer() override;
      87             : 
      88             :     // BEGIN specific public API
      89             : 
      90             :     //! Set the FID column name
      91           0 :     void SetFIDColumn(const char *pszName)
      92             :     {
      93           0 :         osFIDColumn_ = pszName;
      94           0 :     }
      95             : 
      96             :     //! Set the total feature count
      97         130 :     void SetFeatureCount(GIntBig nCount)
      98             :     {
      99         130 :         nFeatureCount_ = nCount;
     100         130 :     }
     101             : 
     102             :     /** Set the file handle.
     103             : 
     104             :      Must be called before GetNextFeature() is called
     105             :      */
     106             :     void SetFile(VSIVirtualHandleUniquePtr &&poFile);
     107             : 
     108             :     /** Set the streaming parser
     109             : 
     110             :      Must be called before GetNextFeature() is called
     111             :      */
     112             :     void SetStreamingParser(
     113             :         std::unique_ptr<OGRJSONFGStreamingParser> &&poStreamingParser);
     114             : 
     115             :     // END specific public API
     116             : 
     117         546 :     const char *GetFIDColumn() const override
     118             :     {
     119         546 :         return osFIDColumn_.c_str();
     120             :     }
     121             : 
     122        1875 :     const OGRFeatureDefn *GetLayerDefn() const override
     123             :     {
     124        1875 :         return poFeatureDefn_;
     125             :     }
     126             : 
     127             :     int TestCapability(const char *pszCap) const override;
     128             : 
     129             :     GIntBig GetFeatureCount(int bForce) override;
     130             : 
     131             :     void ResetReading() override;
     132             : 
     133         358 :     DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRJSONFGStreamedLayer)
     134             : 
     135          16 :     GDALDataset *GetDataset() override
     136             :     {
     137          16 :         return m_poDS;
     138             :     }
     139             : 
     140             :   private:
     141             :     GDALDataset *m_poDS = nullptr;
     142             :     OGRFeatureDefn *poFeatureDefn_ = nullptr;
     143             :     std::string osFIDColumn_{};
     144             : 
     145             :     /** Total number of features. */
     146             :     GIntBig nFeatureCount_ = -1;
     147             : 
     148             :     VSIVirtualHandleUniquePtr poFile_{};
     149             : 
     150             :     std::unique_ptr<OGRJSONFGStreamingParser> poStreamingParser_{};
     151             : 
     152             :     /** Whether a warning has been emitted about feature IDs having been
     153             :      * modified */
     154             :     bool bOriginalIdModified_ = false;
     155             :     /** Set of feature IDs read/allocated up to that point */
     156             :     std::set<GIntBig> oSetUsedFIDs_{};
     157             : 
     158             :     /** Ensure the FID of the feature is unique */
     159             :     OGRFeature *EnsureUniqueFID(OGRFeature *poFeat);
     160             : 
     161             :     /** Return next feature (without filter) */
     162             :     OGRFeature *GetNextRawFeature();
     163             : 
     164             :     CPL_DISALLOW_COPY_ASSIGN(OGRJSONFGStreamedLayer)
     165             : };
     166             : 
     167             : /************************************************************************/
     168             : /*                         OGRJSONFGWriteLayer                          */
     169             : /************************************************************************/
     170             : 
     171             : class OGRJSONFGDataset;
     172             : 
     173             : class OGRJSONFGWriteLayer final : public OGRLayer
     174             : {
     175             :   public:
     176             :     OGRJSONFGWriteLayer(
     177             :         const char *pszName, const OGRSpatialReference *poSRS,
     178             :         std::unique_ptr<OGRCoordinateTransformation> &&poCTToWGS84,
     179             :         const std::string &osCoordRefSys, OGRwkbGeometryType eGType,
     180             :         CSLConstList papszOptions, OGRJSONFGDataset *poDS);
     181             :     ~OGRJSONFGWriteLayer() override;
     182             : 
     183             :     //
     184             :     // OGRLayer Interface
     185             :     //
     186         682 :     const OGRFeatureDefn *GetLayerDefn() const override
     187             :     {
     188         682 :         return poFeatureDefn_;
     189             :     }
     190             : 
     191           1 :     const OGRSpatialReference *GetSpatialRef() const override
     192             :     {
     193           1 :         return nullptr;
     194             :     }
     195             : 
     196          16 :     void ResetReading() override
     197             :     {
     198          16 :     }
     199             : 
     200          16 :     OGRFeature *GetNextFeature() override
     201             :     {
     202          16 :         return nullptr;
     203             :     }
     204             : 
     205             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     206             :     OGRErr CreateField(const OGRFieldDefn *poField, int bApproxOK) override;
     207             :     int TestCapability(const char *pszCap) const override;
     208             : 
     209             :     OGRErr SyncToDisk() override;
     210             : 
     211             :     GDALDataset *GetDataset() override;
     212             : 
     213         125 :     bool HasPolyhedra() const
     214             :     {
     215         125 :         return m_bPolyhedraWritten;
     216             :     }
     217             : 
     218         125 :     bool HasCurve() const
     219             :     {
     220         125 :         return m_bCurveWritten;
     221             :     }
     222             : 
     223         125 :     bool HasMeasure() const
     224             :     {
     225         125 :         return m_bMeasureWritten;
     226             :     }
     227             : 
     228             :   private:
     229             :     OGRJSONFGDataset *poDS_{};
     230             :     OGRFeatureDefn *poFeatureDefn_ = nullptr;
     231             :     std::unique_ptr<OGRCoordinateTransformation> poCTToWGS84_;
     232             :     bool bIsWGS84CRS_ = false;
     233             :     bool m_bMustSwapForPlace = false;
     234             :     int nOutCounter_ = 0;
     235             :     std::string osCoordRefSys_{};
     236             :     bool m_bPolyhedraWritten = false;
     237             :     bool m_bCurveWritten = false;
     238             :     bool m_bMeasureWritten = false;
     239             :     bool bLayerLevelMeasuresWritten_ = false;
     240             :     std::string osMeasureUnit_{};
     241             :     std::string osMeasureDescription_{};
     242             : 
     243             :     OGRGeoJSONWriteOptions oWriteOptions_{};
     244             :     OGRGeoJSONWriteOptions oWriteOptionsPlace_{};
     245             :     bool bWriteFallbackGeometry_ = true;
     246             : 
     247             :     CPL_DISALLOW_COPY_ASSIGN(OGRJSONFGWriteLayer)
     248             : };
     249             : 
     250             : /************************************************************************/
     251             : /*                           OGRJSONFGDataset                           */
     252             : /************************************************************************/
     253             : 
     254             : class OGRJSONFGReader;
     255             : 
     256             : class OGRJSONFGDataset final : public GDALDataset
     257             : {
     258             :   public:
     259         317 :     OGRJSONFGDataset() = default;
     260             :     ~OGRJSONFGDataset() override;
     261             : 
     262             :     CPLErr Close() override;
     263             : 
     264             :     bool Open(GDALOpenInfo *poOpenInfo, GeoJSONSourceType nSrcType);
     265             :     bool Create(const char *pszName, CSLConstList papszOptions);
     266             : 
     267          58 :     int GetLayerCount() const override
     268             :     {
     269          58 :         return static_cast<int>(apoLayers_.size());
     270             :     }
     271             : 
     272             :     const OGRLayer *GetLayer(int i) const override;
     273             : 
     274             :     //! Return the output file handle. Used by OGRJSONFGWriteLayer
     275         296 :     VSILFILE *GetOutputFile() const
     276             :     {
     277         296 :         return fpOut_;
     278             :     }
     279             : 
     280             :     /** Return whether there is a single output layer.
     281             :      * Used by OGRJSONFGWriteLayer
     282             :      */
     283         320 :     bool IsSingleOutputLayer() const
     284             :     {
     285         320 :         return bSingleOutputLayer_;
     286             :     }
     287             : 
     288             :     //! Return whether the output file is seekable
     289           5 :     bool GetFpOutputIsSeekable() const
     290             :     {
     291           5 :         return bFpOutputIsSeekable_;
     292             :     }
     293             : 
     294             :     void BeforeCreateFeature();
     295             : 
     296             :     OGRLayer *ICreateLayer(const char *pszName,
     297             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     298             :                            CSLConstList papszOptions) override;
     299             : 
     300             :     int TestCapability(const char *pszCap) const override;
     301             : 
     302             :     OGRErr SyncToDiskInternal();
     303             : 
     304             :   protected:
     305             :     friend class OGRJSONFGReader;
     306             :     OGRJSONFGMemLayer *AddLayer(std::unique_ptr<OGRJSONFGMemLayer> &&poLayer);
     307             :     OGRJSONFGStreamedLayer *
     308             :     AddLayer(std::unique_ptr<OGRJSONFGStreamedLayer> &&poLayer);
     309             : 
     310             :   private:
     311             :     char *pszGeoData_ = nullptr;
     312             :     size_t nGeoDataLen_ = 0;
     313             :     std::vector<std::unique_ptr<OGRLayer>> apoLayers_{};
     314             :     std::unique_ptr<OGRJSONFGReader> poReader_{};
     315             : 
     316             :     // Write side
     317             :     VSILFILE *fpOut_ = nullptr;
     318             :     vsi_l_offset m_nPositionBeforeConformsTo = 0;
     319             :     vsi_l_offset m_nPositionAfterConformsTo = 0;
     320             :     bool bSingleOutputLayer_ = false;
     321             :     bool bHasEmittedFeatures_ = false;
     322             :     bool bFpOutputIsSeekable_ = false;
     323             : 
     324             :     /** Offset at which the '] }' terminating sequence has already been
     325             :      * written by SyncToDisk(). 0 if it has not been written.
     326             :      */
     327             :     vsi_l_offset m_nPositionBeforeFCClosed = 0;
     328             : 
     329             :     bool ReadFromFile(GDALOpenInfo *poOpenInfo, const char *pszUnprefixed);
     330             :     bool ReadFromService(GDALOpenInfo *poOpenInfo, const char *pszSource);
     331             : 
     332             :     bool FinishWriting();
     333             : 
     334             :     bool EmitStartFeaturesIfNeededAndReturnIfFirstFeature();
     335             : 
     336             :     CPL_DISALLOW_COPY_ASSIGN(OGRJSONFGDataset)
     337             : };
     338             : 
     339             : /************************************************************************/
     340             : /*                          OGRJSONFGReader                             */
     341             : /************************************************************************/
     342             : 
     343             : class OGRJSONFGReader
     344             : {
     345             :   public:
     346         232 :     OGRJSONFGReader() = default;
     347             :     ~OGRJSONFGReader();
     348             : 
     349             :     /** Load all features from the passed in JSON text in OGRJSONFGMemLayer(s)
     350             :      *
     351             :      * This method should only be called once, and is exclusive with
     352             :      * AnalyzeWithStreamingParser()
     353             :      */
     354             :     bool Load(OGRJSONFGDataset *poDS, const char *pszText,
     355             :               const std::string &osDefaultLayerName);
     356             : 
     357             :     /** Do a first pass analysis of the content of the passed file to create
     358             :      * OGRJSONFGStreamedLayer's
     359             :      *
     360             :      * It is the responsibility of the caller to call
     361             :      * SetFile() and SetStreamingParser() on the created layers afterwards
     362             :      *
     363             :      * This method should only be called once, and is exclusive with
     364             :      * Load()
     365             :      */
     366             :     bool AnalyzeWithStreamingParser(OGRJSONFGDataset *poDS, VSILFILE *fp,
     367             :                                     const std::string &osDefaultLayerName,
     368             :                                     bool &bCanTryWithNonStreamingParserOut,
     369             :                                     bool &bHasTopLevelMeasures);
     370             : 
     371             :     /** Geometry element we are interested in. */
     372             :     enum class GeometryElement
     373             :     {
     374             :         /** Use "place" when possible, fallback to "geometry" otherwise. */
     375             :         AUTO,
     376             :         /** Only use "place" */
     377             :         PLACE,
     378             :         /** Only use "geometry" */
     379             :         GEOMETRY,
     380             :     };
     381             : 
     382             :     /** Sets the geometry element we are interested in. */
     383           6 :     void SetGeometryElement(GeometryElement elt)
     384             :     {
     385           6 :         eGeometryElement_ = elt;
     386           6 :     }
     387             : 
     388             :     /** Returns a OGRFeature built from the passed in JSON object.
     389             :      *
     390             :      * @param poObj JSON feature
     391             :      * @param pszRequestedLayer name of the layer of interest, or nullptr if
     392             :      * no filtering needed on the layer name. If the feature does not belong
     393             :      * to the requested layer, nullptr is returned.
     394             :      * @param bHasM Whether the upper level of this object has measures
     395             :      * @param pOutMemLayer Pointer to the OGRJSONFGMemLayer* layer to which
     396             :      * the returned feature belongs to. May be nullptr. Only applies when
     397             :      * the Load() method has been used.
     398             :      * @param pOutStreamedLayer Pointer to the OGRJSONFGStreamedLayer* layer to
     399             :      * which the returned feature belongs to. May be nullptr. Only applies when
     400             :      * the AnalyzeWithStreamingParser() method has been used.
     401             :      */
     402             :     std::unique_ptr<OGRFeature>
     403             :     ReadFeature(json_object *poObj, const char *pszRequestedLayer, bool bHasM,
     404             :                 OGRJSONFGMemLayer **pOutMemLayer,
     405             :                 OGRJSONFGStreamedLayer **pOutStreamedLayer);
     406             : 
     407             :   protected:
     408             :     friend class OGRJSONFGStreamingParser;
     409             : 
     410             :     bool GenerateLayerDefnFromFeature(json_object *poObj);
     411             : 
     412             :   private:
     413             :     GeometryElement eGeometryElement_ = GeometryElement::AUTO;
     414             : 
     415             :     OGRJSONFGDataset *poDS_ = nullptr;
     416             :     std::string osDefaultLayerName_{};
     417             :     json_object *poObject_ = nullptr;
     418             : 
     419             :     bool bFlattenNestedAttributes_ = false;
     420             :     char chNestedAttributeSeparator_ = 0;
     421             :     bool bArrayAsString_ = false;
     422             :     bool bDateAsString_ = false;
     423             :     std::string osMeasureUnit_{};
     424             :     std::string osMeasureDescription_{};
     425             : 
     426             :     /** Layer building context, specific to one layer. */
     427         225 :     struct LayerDefnBuildContext
     428             :     {
     429             :         //! Maps a field name to its index in apoFieldDefn[]
     430             :         std::map<std::string, int> oMapFieldNameToIdx{};
     431             : 
     432             :         //! Vector of OGRFieldDefn
     433             :         std::vector<std::unique_ptr<OGRFieldDefn>> apoFieldDefn{};
     434             : 
     435             :         //! Directed acyclic graph used to build the order of fields.
     436             :         gdal::DirectedAcyclicGraph<int, std::string> dag{};
     437             : 
     438             :         /** Set of indices of apoFieldDefn[] for which no type information is
     439             :          * known yet. */
     440             :         std::set<int> aoSetUndeterminedTypeFields{};
     441             : 
     442             :         //! Whether at least one feature has a "coordRefSys" member.
     443             :         bool bHasCoordRefSysAtFeatureLevel = false;
     444             : 
     445             :         /** CRS object corresponding to "coordRefsys" member at feature level.
     446             :          * Only set if homogeneous among features.
     447             :          */
     448             :         std::unique_ptr<OGRSpatialReference> poCRSAtFeatureLevel{};
     449             : 
     450             :         /** Serialized JSON value of "coordRefsys" member at feature level.
     451             :          * Only set if homogeneous among features.
     452             :          */
     453             :         std::string osCoordRefSysAtFeatureLevel{};
     454             : 
     455             :         /** Whether to switch X/Y ordinates in geometries appearing in "place"
     456             :          * element. Only applies to CRS at layer level.
     457             :          */
     458             :         bool bSwapPlacesXY = false;
     459             : 
     460             :         //! Whether the layer CRS is WGS 84.
     461             :         bool bLayerCRSIsWGS84 = false;
     462             : 
     463             :         //! Coordinate transformation from WGS 84 to layer CRS (might be null)
     464             :         std::unique_ptr<OGRCoordinateTransformation> poCTWGS84ToLayerCRS{};
     465             : 
     466             :         /** Feature count */
     467             :         GIntBig nFeatureCount = 0;
     468             : 
     469             :         //! Whether the Feature.id should be mapped to a OGR field.
     470             :         bool bFeatureLevelIdAsAttribute = false;
     471             : 
     472             :         //! Whether the Feature.id should be mapped to a OGR FID.
     473             :         bool bFeatureLevelIdAsFID = false;
     474             : 
     475             :         //! Whether 64-bit integers are needed for OGR FID.
     476             :         bool bNeedFID64 = false;
     477             : 
     478             :         //! Whether detection of layer geometry type is still needed.
     479             :         bool bDetectLayerGeomType = true;
     480             : 
     481             :         //! Whether no geometry has been analyzed yet.
     482             :         bool bFirstGeometry = true;
     483             : 
     484             :         //! Layer geometry type.
     485             :         OGRwkbGeometryType eLayerGeomType = wkbUnknown;
     486             : 
     487             :         //! Whether a Feature.time.date element has been found.
     488             :         bool bHasTimeDate = false;
     489             : 
     490             :         //! Whether a Feature.time.timestamp element has been found.
     491             :         bool bHasTimeTimestamp = false;
     492             : 
     493             :         /** Whether a Feature.time.interval[0] element of type timestamp has
     494             :          * been found */
     495             :         bool bHasTimeIntervalStartTimestamp = false;
     496             : 
     497             :         /** Whether a Feature.time.interval[0] element of type date has
     498             :          * been found */
     499             :         bool bHasTimeIntervalStartDate = false;
     500             : 
     501             :         /** Whether a Feature.time.interval[1] element of type timestamp has
     502             :          * been found */
     503             :         bool bHasTimeIntervalEndTimestamp = false;
     504             : 
     505             :         /** Whether a Feature.time.interval[1] element of type date has
     506             :          * been found */
     507             :         bool bHasTimeIntervalEndDate = false;
     508             : 
     509             :         //! Index of OGR field "time" / "jsonfg_time"
     510             :         int nIdxFieldTime = -1;
     511             : 
     512             :         //! Index of OGR field "time_start" / "jsonfg_time_start"
     513             :         int nIdxFieldTimeStart = -1;
     514             : 
     515             :         //! Index of OGR field "time_end" / "jsonfg_time_end"
     516             :         int nIdxFieldTimeEnd = -1;
     517             : 
     518             :         //! Corresponding OGRJSONFGMemLayer (only for Load() ingestion mode)
     519             :         OGRJSONFGMemLayer *poMemLayer = nullptr;
     520             : 
     521             :         /** Corresponding OGRJSONFGStreamedLayer(only for
     522             :          * AnalyzeWithStreamingParser() mode) */
     523             :         OGRJSONFGStreamedLayer *poStreamedLayer = nullptr;
     524             : 
     525             :         bool bSameMeasureMetadata = true;
     526             : 
     527             :         //! Measure unit
     528             :         std::string osMeasureUnit{};
     529             : 
     530             :         //! Measure description
     531             :         std::string osMeasureDescription{};
     532             : 
     533         431 :         LayerDefnBuildContext() = default;
     534          19 :         LayerDefnBuildContext(LayerDefnBuildContext &&) = default;
     535             :         LayerDefnBuildContext &operator=(LayerDefnBuildContext &&) = default;
     536             : 
     537             :       private:
     538             :         CPL_DISALLOW_COPY_ASSIGN(LayerDefnBuildContext)
     539             :     };
     540             : 
     541             :     //! Maps a layer name to its build context
     542             :     std::map<std::string, LayerDefnBuildContext> oMapBuildContext_{};
     543             : 
     544             :     //
     545             :     // Copy operations not supported.
     546             :     //
     547             :     CPL_DISALLOW_COPY_ASSIGN(OGRJSONFGReader)
     548             : 
     549             :     const char *GetLayerNameForFeature(json_object *poObj) const;
     550             :     bool GenerateLayerDefns();
     551             :     bool FinalizeGenerateLayerDefns(bool bStreamedLayer);
     552             :     void FinalizeBuildContext(LayerDefnBuildContext &oBuildContext,
     553             :                               const char *pszLayerName, bool bStreamedLayer,
     554             :                               bool bInvalidCRS, bool bSwapPlacesXYTopLevel,
     555             :                               OGRSpatialReference *poSRSTopLevel);
     556             : };
     557             : 
     558             : /************************************************************************/
     559             : /*                      OGRJSONFGStreamingParser                        */
     560             : /************************************************************************/
     561             : 
     562             : /** FeatureCollection streaming parser. */
     563         600 : class OGRJSONFGStreamingParser final : public OGRJSONCollectionStreamingParser
     564             : {
     565             :     OGRJSONFGReader &m_oReader;
     566             :     std::string m_osRequestedLayer{};
     567             : 
     568             :     std::vector<std::pair<std::unique_ptr<OGRFeature>, OGRLayer *>>
     569             :         m_apoFeatures{};
     570             :     size_t m_nCurFeatureIdx = 0;
     571             : 
     572             :     CPL_DISALLOW_COPY_ASSIGN(OGRJSONFGStreamingParser)
     573             : 
     574             :   protected:
     575             :     void GotFeature(json_object *poObj, bool bFirstPass,
     576             :                     const std::string &osJson) override;
     577             :     void TooComplex() override;
     578             : 
     579             :   public:
     580             :     OGRJSONFGStreamingParser(OGRJSONFGReader &oReader, bool bFirstPass,
     581             :                              bool bHasTopLevelMeasures);
     582             :     ~OGRJSONFGStreamingParser() override;
     583             : 
     584         130 :     void SetRequestedLayer(const char *pszRequestedLayer)
     585             :     {
     586         130 :         m_osRequestedLayer = pszRequestedLayer;
     587         130 :     }
     588             : 
     589             :     std::unique_ptr<OGRJSONFGStreamingParser> Clone();
     590             : 
     591             :     std::pair<std::unique_ptr<OGRFeature>, OGRLayer *> GetNextFeature();
     592             : };
     593             : 
     594             : bool OGRJSONFGMustSwapXY(const OGRSpatialReference *poSRS);
     595             : 
     596             : #endif  // OGR_JSONFG_H_INCLUDED

Generated by: LCOV version 1.14