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 96 : OGRJSONFGStreamedLayer::OGRJSONFGStreamedLayer(GDALDataset *poDS, 20 : const char *pszName, 21 : OGRSpatialReference *poSRS, 22 96 : OGRwkbGeometryType eGType) 23 96 : : m_poDS(poDS), poFeatureDefn_(new OGRFeatureDefn(pszName)) 24 : { 25 : 26 96 : poFeatureDefn_->Reference(); 27 : 28 96 : SetDescription(poFeatureDefn_->GetName()); 29 96 : poFeatureDefn_->SetGeomType(eGType); 30 : 31 96 : if (eGType != wkbNone && poSRS != nullptr) 32 : { 33 95 : OGRSpatialReference *poSRSClone = poSRS->Clone(); 34 95 : poFeatureDefn_->GetGeomFieldDefn(0)->SetSpatialRef(poSRSClone); 35 95 : poSRSClone->Release(); 36 : } 37 : 38 96 : poFeatureDefn_->Seal(/* bSealFields = */ true); 39 96 : } 40 : 41 : /************************************************************************/ 42 : /* OGRJSONFGStreamedLayer::~OGRJSONFGStreamedLayer() */ 43 : /************************************************************************/ 44 : 45 192 : OGRJSONFGStreamedLayer::~OGRJSONFGStreamedLayer() 46 : { 47 96 : poFeatureDefn_->Release(); 48 192 : } 49 : 50 : /************************************************************************/ 51 : /* SetFile() */ 52 : /************************************************************************/ 53 : 54 96 : void OGRJSONFGStreamedLayer::SetFile(VSIVirtualHandleUniquePtr &&poFile) 55 : { 56 96 : poFile_ = std::move(poFile); 57 96 : poFile_->Seek(0, SEEK_SET); 58 96 : } 59 : 60 : /************************************************************************/ 61 : /* SetStreamingParser() */ 62 : /************************************************************************/ 63 : 64 96 : void OGRJSONFGStreamedLayer::SetStreamingParser( 65 : std::unique_ptr<OGRJSONFGStreamingParser> &&poStreamingParser) 66 : { 67 96 : poStreamingParser_ = std::move(poStreamingParser); 68 96 : poStreamingParser_->SetRequestedLayer(GetName()); 69 96 : } 70 : 71 : /************************************************************************/ 72 : /* ResetReading() */ 73 : /************************************************************************/ 74 : 75 103 : void OGRJSONFGStreamedLayer::ResetReading() 76 : { 77 103 : CPLAssert(poFile_); 78 103 : CPLAssert(poStreamingParser_); 79 103 : poStreamingParser_ = poStreamingParser_->Clone(); 80 103 : poFile_->Seek(0, SEEK_SET); 81 103 : oSetUsedFIDs_.clear(); 82 103 : } 83 : 84 : /************************************************************************/ 85 : /* EnsureUniqueFID() */ 86 : /************************************************************************/ 87 : 88 388 : OGRFeature *OGRJSONFGStreamedLayer::EnsureUniqueFID(OGRFeature *poFeat) 89 : { 90 388 : GIntBig nFID = poFeat->GetFID(); 91 388 : if (nFID == OGRNullFID) 92 : { 93 358 : nFID = static_cast<GIntBig>(oSetUsedFIDs_.size()); 94 358 : 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 388 : oSetUsedFIDs_.insert(nFID); 118 388 : poFeat->SetFID(nFID); 119 388 : return poFeat; 120 : } 121 : 122 : /************************************************************************/ 123 : /* GetNextRawFeature() */ 124 : /************************************************************************/ 125 : 126 419 : OGRFeature *OGRJSONFGStreamedLayer::GetNextRawFeature() 127 : { 128 419 : CPLAssert(poFile_); 129 419 : CPLAssert(poStreamingParser_); 130 : 131 838 : auto poFeatAndLayer = poStreamingParser_->GetNextFeature(); 132 419 : if (poFeatAndLayer.first) 133 : { 134 295 : return EnsureUniqueFID(poFeatAndLayer.first.release()); 135 : } 136 : 137 248 : std::vector<GByte> abyBuffer; 138 124 : abyBuffer.resize(4096 * 10); 139 : while (true) 140 : { 141 124 : size_t nRead = poFile_->Read(abyBuffer.data(), 1, abyBuffer.size()); 142 124 : const bool bFinished = nRead < abyBuffer.size(); 143 248 : if (!poStreamingParser_->Parse( 144 124 : reinterpret_cast<const char *>(abyBuffer.data()), nRead, 145 372 : bFinished) || 146 124 : poStreamingParser_->ExceptionOccurred()) 147 : { 148 0 : break; 149 : } 150 : 151 124 : poFeatAndLayer = poStreamingParser_->GetNextFeature(); 152 124 : if (poFeatAndLayer.first) 153 : { 154 93 : return EnsureUniqueFID(poFeatAndLayer.first.release()); 155 : } 156 31 : if (bFinished) 157 31 : break; 158 0 : } 159 : 160 31 : return nullptr; 161 : } 162 : 163 : /************************************************************************/ 164 : /* TestCapability() */ 165 : /************************************************************************/ 166 : 167 36 : int OGRJSONFGStreamedLayer::TestCapability(const char *pszCap) 168 : 169 : { 170 36 : if (EQUAL(pszCap, OLCFastFeatureCount)) 171 0 : return !m_poFilterGeom && !m_poAttrQuery && nFeatureCount_ >= 0; 172 : 173 36 : else if (EQUAL(pszCap, OLCStringsAsUTF8)) 174 13 : return TRUE; 175 : 176 23 : else if (EQUAL(pszCap, OLCZGeometries)) 177 3 : return TRUE; 178 : 179 20 : return FALSE; 180 : } 181 : 182 : /************************************************************************/ 183 : /* GetFeatureCount() */ 184 : /************************************************************************/ 185 : 186 19 : GIntBig OGRJSONFGStreamedLayer::GetFeatureCount(int bForce) 187 : { 188 19 : if (!m_poFilterGeom && !m_poAttrQuery && nFeatureCount_ >= 0) 189 13 : return nFeatureCount_; 190 6 : return OGRLayer::GetFeatureCount(bForce); 191 : }