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 : #include "ogr_jsonfg.h" 14 : 15 : /************************************************************************/ 16 : /* OGRJSONFGStreamedLayer::OGRJSONFGStreamedLayer() */ 17 : /************************************************************************/ 18 : 19 130 : OGRJSONFGStreamedLayer::OGRJSONFGStreamedLayer(GDALDataset *poDS, 20 : const char *pszName, 21 : OGRSpatialReference *poSRS, 22 130 : OGRwkbGeometryType eGType) 23 130 : : m_poDS(poDS), poFeatureDefn_(new OGRFeatureDefn(pszName)) 24 : { 25 : 26 130 : poFeatureDefn_->Reference(); 27 : 28 130 : SetDescription(poFeatureDefn_->GetName()); 29 130 : poFeatureDefn_->SetGeomType(eGType); 30 : 31 130 : if (eGType != wkbNone && poSRS != nullptr) 32 : { 33 129 : OGRSpatialReference *poSRSClone = poSRS->Clone(); 34 129 : poFeatureDefn_->GetGeomFieldDefn(0)->SetSpatialRef(poSRSClone); 35 129 : poSRSClone->Release(); 36 : } 37 : 38 130 : poFeatureDefn_->Seal(/* bSealFields = */ true); 39 130 : } 40 : 41 : /************************************************************************/ 42 : /* OGRJSONFGStreamedLayer::~OGRJSONFGStreamedLayer() */ 43 : /************************************************************************/ 44 : 45 260 : OGRJSONFGStreamedLayer::~OGRJSONFGStreamedLayer() 46 : { 47 130 : poFeatureDefn_->Release(); 48 260 : } 49 : 50 : /************************************************************************/ 51 : /* SetFile() */ 52 : /************************************************************************/ 53 : 54 130 : void OGRJSONFGStreamedLayer::SetFile(VSIVirtualHandleUniquePtr &&poFile) 55 : { 56 130 : poFile_ = std::move(poFile); 57 130 : poFile_->Seek(0, SEEK_SET); 58 130 : } 59 : 60 : /************************************************************************/ 61 : /* SetStreamingParser() */ 62 : /************************************************************************/ 63 : 64 130 : void OGRJSONFGStreamedLayer::SetStreamingParser( 65 : std::unique_ptr<OGRJSONFGStreamingParser> &&poStreamingParser) 66 : { 67 130 : poStreamingParser_ = std::move(poStreamingParser); 68 130 : poStreamingParser_->SetRequestedLayer(GetName()); 69 130 : } 70 : 71 : /************************************************************************/ 72 : /* ResetReading() */ 73 : /************************************************************************/ 74 : 75 107 : void OGRJSONFGStreamedLayer::ResetReading() 76 : { 77 107 : CPLAssert(poFile_); 78 107 : CPLAssert(poStreamingParser_); 79 107 : poStreamingParser_ = poStreamingParser_->Clone(); 80 107 : poFile_->Seek(0, SEEK_SET); 81 107 : oSetUsedFIDs_.clear(); 82 107 : } 83 : 84 : /************************************************************************/ 85 : /* EnsureUniqueFID() */ 86 : /************************************************************************/ 87 : 88 431 : OGRFeature *OGRJSONFGStreamedLayer::EnsureUniqueFID(OGRFeature *poFeat) 89 : { 90 431 : GIntBig nFID = poFeat->GetFID(); 91 431 : if (nFID == OGRNullFID) 92 : { 93 401 : nFID = static_cast<GIntBig>(oSetUsedFIDs_.size()); 94 401 : while (oSetUsedFIDs_.find(nFID) != oSetUsedFIDs_.end()) 95 : { 96 0 : ++nFID; 97 : } 98 : } 99 30 : else if (oSetUsedFIDs_.find(nFID) != oSetUsedFIDs_.end()) 100 : { 101 0 : if (!bOriginalIdModified_) 102 : { 103 0 : CPLError(CE_Warning, CPLE_AppDefined, 104 : "Several features with id = " CPL_FRMT_GIB " have " 105 : "been found. Altering it to be unique. " 106 : "This warning will not be emitted anymore for " 107 : "this layer", 108 : nFID); 109 0 : bOriginalIdModified_ = true; 110 : } 111 0 : nFID = static_cast<GIntBig>(oSetUsedFIDs_.size()); 112 0 : while (oSetUsedFIDs_.find(nFID) != oSetUsedFIDs_.end()) 113 : { 114 0 : ++nFID; 115 : } 116 : } 117 431 : oSetUsedFIDs_.insert(nFID); 118 431 : poFeat->SetFID(nFID); 119 431 : return poFeat; 120 : } 121 : 122 : /************************************************************************/ 123 : /* GetNextRawFeature() */ 124 : /************************************************************************/ 125 : 126 467 : OGRFeature *OGRJSONFGStreamedLayer::GetNextRawFeature() 127 : { 128 467 : CPLAssert(poFile_); 129 467 : CPLAssert(poStreamingParser_); 130 : 131 934 : auto poFeatAndLayer = poStreamingParser_->GetNextFeature(); 132 467 : if (poFeatAndLayer.first) 133 : { 134 304 : return EnsureUniqueFID(poFeatAndLayer.first.release()); 135 : } 136 : 137 326 : std::vector<GByte> abyBuffer; 138 163 : abyBuffer.resize(4096 * 10); 139 : while (true) 140 : { 141 163 : size_t nRead = poFile_->Read(abyBuffer.data(), 1, abyBuffer.size()); 142 163 : const bool bFinished = nRead < abyBuffer.size(); 143 326 : if (!poStreamingParser_->Parse( 144 : std::string_view( 145 163 : reinterpret_cast<const char *>(abyBuffer.data()), nRead), 146 489 : bFinished) || 147 163 : poStreamingParser_->ExceptionOccurred()) 148 : { 149 0 : break; 150 : } 151 : 152 163 : poFeatAndLayer = poStreamingParser_->GetNextFeature(); 153 163 : if (poFeatAndLayer.first) 154 : { 155 127 : return EnsureUniqueFID(poFeatAndLayer.first.release()); 156 : } 157 36 : if (bFinished) 158 36 : break; 159 0 : } 160 : 161 36 : return nullptr; 162 : } 163 : 164 : /************************************************************************/ 165 : /* TestCapability() */ 166 : /************************************************************************/ 167 : 168 39 : int OGRJSONFGStreamedLayer::TestCapability(const char *pszCap) const 169 : 170 : { 171 39 : if (EQUAL(pszCap, OLCFastFeatureCount)) 172 0 : return !m_poFilterGeom && !m_poAttrQuery && nFeatureCount_ >= 0; 173 : 174 39 : else if (EQUAL(pszCap, OLCStringsAsUTF8)) 175 13 : return TRUE; 176 : 177 26 : else if (EQUAL(pszCap, OLCZGeometries) || 178 23 : EQUAL(pszCap, OLCMeasuredGeometries) || 179 19 : EQUAL(pszCap, OLCCurveGeometries)) 180 : { 181 11 : return TRUE; 182 : } 183 : 184 15 : return FALSE; 185 : } 186 : 187 : /************************************************************************/ 188 : /* GetFeatureCount() */ 189 : /************************************************************************/ 190 : 191 19 : GIntBig OGRJSONFGStreamedLayer::GetFeatureCount(int bForce) 192 : { 193 19 : if (!m_poFilterGeom && !m_poAttrQuery && nFeatureCount_ >= 0) 194 13 : return nFeatureCount_; 195 6 : return OGRLayer::GetFeatureCount(bForce); 196 : }