LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/idrisi - ogridrisilayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 262 320 81.9 %
Date: 2026-01-23 20:24:11 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Idrisi Translator
       4             :  * Purpose:  Implements OGRIdrisiLayer class.
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2011-2013, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_conv.h"
      14             : #include "cpl_string.h"
      15             : #include "ogr_idrisi.h"
      16             : #include "ogr_p.h"
      17             : #include "ogr_srs_api.h"
      18             : 
      19             : /************************************************************************/
      20             : /*                         OGRIdrisiLayer()                             */
      21             : /************************************************************************/
      22             : 
      23           3 : OGRIdrisiLayer::OGRIdrisiLayer(const char *pszFilename,
      24             :                                const char *pszLayerName, VSILFILE *fpIn,
      25             :                                OGRwkbGeometryType eGeomTypeIn,
      26           3 :                                const char *pszWTKString)
      27           3 :     : poFeatureDefn(new OGRFeatureDefn(pszLayerName)), poSRS(nullptr),
      28             :       eGeomType(eGeomTypeIn), fp(fpIn), fpAVL(nullptr), bEOF(false),
      29             :       nNextFID(1), bExtentValid(false), dfMinX(0.0), dfMinY(0.0), dfMaxX(0.0),
      30           3 :       dfMaxY(0.0), nTotalFeatures(0)
      31             : {
      32           3 :     if (pszWTKString)
      33             :     {
      34           3 :         poSRS = new OGRSpatialReference();
      35           3 :         poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
      36           3 :         poSRS->importFromWkt(pszWTKString);
      37             :     }
      38             : 
      39           3 :     SetDescription(poFeatureDefn->GetName());
      40           3 :     poFeatureDefn->Reference();
      41           3 :     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
      42           3 :     poFeatureDefn->SetGeomType(eGeomType);
      43             : 
      44           6 :     OGRFieldDefn oFieldDefn("id", OFTReal);
      45           3 :     poFeatureDefn->AddFieldDefn(&oFieldDefn);
      46             : 
      47           3 :     VSIFSeekL(fp, 1, SEEK_SET);
      48           3 :     if (VSIFReadL(&nTotalFeatures, sizeof(unsigned int), 1, fp) != 1)
      49           0 :         nTotalFeatures = 0;
      50           3 :     CPL_LSBPTR32(&nTotalFeatures);
      51             : 
      52           3 :     if (nTotalFeatures != 0)
      53             :     {
      54           3 :         if (!Detect_AVL_ADC(pszFilename))
      55             :         {
      56           2 :             if (fpAVL != nullptr)
      57           0 :                 VSIFCloseL(fpAVL);
      58           2 :             fpAVL = nullptr;
      59             :         }
      60             :     }
      61             : 
      62           3 :     OGRIdrisiLayer::ResetReading();
      63           3 : }
      64             : 
      65             : /************************************************************************/
      66             : /*                          ~OGRIdrisiLayer()                           */
      67             : /************************************************************************/
      68             : 
      69           6 : OGRIdrisiLayer::~OGRIdrisiLayer()
      70             : 
      71             : {
      72           3 :     if (poSRS != nullptr)
      73           3 :         poSRS->Release();
      74             : 
      75           3 :     poFeatureDefn->Release();
      76             : 
      77           3 :     VSIFCloseL(fp);
      78             : 
      79           3 :     if (fpAVL != nullptr)
      80           1 :         VSIFCloseL(fpAVL);
      81           6 : }
      82             : 
      83             : /************************************************************************/
      84             : /*                           Detect_AVL_ADC()                           */
      85             : /************************************************************************/
      86             : 
      87           3 : bool OGRIdrisiLayer::Detect_AVL_ADC(const char *pszFilename)
      88             : {
      89             :     // --------------------------------------------------------------------
      90             :     //      Look for .adc file
      91             :     // --------------------------------------------------------------------
      92           6 :     std::string osADCFilename = CPLResetExtensionSafe(pszFilename, "adc");
      93           3 :     VSILFILE *fpADC = VSIFOpenL(osADCFilename.c_str(), "rb");
      94           3 :     if (fpADC == nullptr)
      95             :     {
      96           2 :         osADCFilename = CPLResetExtensionSafe(pszFilename, "ADC");
      97           2 :         fpADC = VSIFOpenL(osADCFilename.c_str(), "rb");
      98             :     }
      99             : 
     100           3 :     char **papszADC = nullptr;
     101           3 :     if (fpADC != nullptr)
     102             :     {
     103           1 :         VSIFCloseL(fpADC);
     104           1 :         fpADC = nullptr;
     105             : 
     106           1 :         CPLPushErrorHandler(CPLQuietErrorHandler);
     107           1 :         papszADC = CSLLoad2(osADCFilename.c_str(), 1024, 256, nullptr);
     108           1 :         CPLPopErrorHandler();
     109           1 :         CPLErrorReset();
     110             :     }
     111             : 
     112           3 :     if (papszADC == nullptr)
     113           2 :         return false;
     114             : 
     115           1 :     CSLSetNameValueSeparator(papszADC, ":");
     116             : 
     117           1 :     const char *pszVersion = CSLFetchNameValue(papszADC, "file format");
     118           1 :     if (pszVersion == nullptr || !EQUAL(pszVersion, "IDRISI Values A.1"))
     119             :     {
     120           0 :         CSLDestroy(papszADC);
     121           0 :         return false;
     122             :     }
     123             : 
     124           1 :     const char *pszFileType = CSLFetchNameValue(papszADC, "file type");
     125           1 :     if (pszFileType == nullptr || !EQUAL(pszFileType, "ascii"))
     126             :     {
     127           0 :         CPLDebug("IDRISI", ".adc file found, but file type != ascii");
     128           0 :         CSLDestroy(papszADC);
     129           0 :         return false;
     130             :     }
     131             : 
     132           1 :     const char *pszRecords = CSLFetchNameValue(papszADC, "records");
     133           1 :     if (pszRecords == nullptr || atoi(pszRecords) != (int)nTotalFeatures)
     134             :     {
     135           0 :         CPLDebug("IDRISI", ".adc file found, but 'records' not found or not "
     136             :                            "consistent with feature number declared in .vdc");
     137           0 :         CSLDestroy(papszADC);
     138           0 :         return false;
     139             :     }
     140             : 
     141           1 :     const char *pszFields = CSLFetchNameValue(papszADC, "fields");
     142           1 :     if (pszFields == nullptr || atoi(pszFields) <= 1)
     143             :     {
     144           0 :         CPLDebug("IDRISI",
     145             :                  ".adc file found, but 'fields' not found or invalid");
     146           0 :         CSLDestroy(papszADC);
     147           0 :         return false;
     148             :     }
     149             : 
     150             :     // --------------------------------------------------------------------
     151             :     //      Look for .avl file
     152             :     // --------------------------------------------------------------------
     153           2 :     std::string osAVLFilename = CPLResetExtensionSafe(pszFilename, "avl");
     154           1 :     fpAVL = VSIFOpenL(osAVLFilename.c_str(), "rb");
     155           1 :     if (fpAVL == nullptr)
     156             :     {
     157           0 :         osAVLFilename = CPLResetExtensionSafe(pszFilename, "AVL");
     158           0 :         fpAVL = VSIFOpenL(osAVLFilename.c_str(), "rb");
     159             :     }
     160           1 :     if (fpAVL == nullptr)
     161             :     {
     162           0 :         CSLDestroy(papszADC);
     163           0 :         return false;
     164             :     }
     165             : 
     166             :     // --------------------------------------------------------------------
     167             :     //      Build layer definition
     168             :     // --------------------------------------------------------------------
     169             : 
     170             :     char szKey[32];
     171           1 :     int iCurField = 0;
     172           1 :     snprintf(szKey, sizeof(szKey), "field %d", iCurField);
     173             : 
     174           1 :     char **papszIter = papszADC;
     175           1 :     const char *pszLine = nullptr;
     176           1 :     bool bFieldFound = false;
     177           2 :     CPLString osFieldName;
     178          14 :     while ((pszLine = *papszIter) != nullptr)
     179             :     {
     180             :         // CPLDebug("IDRISI", "%s", pszLine);
     181          13 :         if (strncmp(pszLine, szKey, strlen(szKey)) == 0)
     182             :         {
     183           4 :             const char *pszColon = strchr(pszLine, ':');
     184           4 :             if (pszColon)
     185             :             {
     186           4 :                 osFieldName = pszColon + 1;
     187           4 :                 bFieldFound = true;
     188             :             }
     189             :         }
     190           9 :         else if (bFieldFound && STARTS_WITH(pszLine, "data type:"))
     191             :         {
     192           4 :             const char *pszFieldType = pszLine + strlen("data type:");
     193             : 
     194             :             OGRFieldDefn oFieldDefn(osFieldName.c_str(),
     195           4 :                                     EQUAL(pszFieldType, "integer") ? OFTInteger
     196           2 :                                     : EQUAL(pszFieldType, "real")  ? OFTReal
     197           6 :                                                                    : OFTString);
     198             : 
     199           4 :             if (iCurField == 0 && oFieldDefn.GetType() != OFTInteger)
     200             :             {
     201           0 :                 CSLDestroy(papszADC);
     202           0 :                 return false;
     203             :             }
     204             : 
     205           4 :             if (iCurField != 0)
     206           3 :                 poFeatureDefn->AddFieldDefn(&oFieldDefn);
     207             : 
     208           4 :             iCurField++;
     209           4 :             snprintf(szKey, sizeof(szKey), "field %d", iCurField);
     210             :         }
     211             : 
     212          13 :         papszIter++;
     213             :     }
     214             : 
     215           1 :     CSLDestroy(papszADC);
     216             : 
     217           1 :     return true;
     218             : }
     219             : 
     220             : /************************************************************************/
     221             : /*                            ResetReading()                            */
     222             : /************************************************************************/
     223             : 
     224          11 : void OGRIdrisiLayer::ResetReading()
     225             : 
     226             : {
     227          11 :     nNextFID = 1;
     228          11 :     bEOF = false;
     229          11 :     VSIFSeekL(fp, 0x105, SEEK_SET);
     230          11 :     if (fpAVL != nullptr)
     231           5 :         VSIFSeekL(fpAVL, 0, SEEK_SET);
     232          11 : }
     233             : 
     234             : /************************************************************************/
     235             : /*                           TestCapability()                           */
     236             : /************************************************************************/
     237             : 
     238           6 : int OGRIdrisiLayer::TestCapability(const char *pszCap) const
     239             : 
     240             : {
     241           6 :     if (EQUAL(pszCap, OLCFastFeatureCount))
     242           3 :         return m_poFilterGeom == nullptr && m_poAttrQuery == nullptr;
     243             : 
     244           3 :     if (EQUAL(pszCap, OLCFastGetExtent))
     245           3 :         return bExtentValid;
     246             : 
     247           0 :     return FALSE;
     248             : }
     249             : 
     250             : /************************************************************************/
     251             : /*                         GetNextRawFeature()                          */
     252             : /************************************************************************/
     253             : 
     254          10 : OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
     255             : {
     256          10 :     if (bEOF)
     257           0 :         return nullptr;
     258             : 
     259             :     while (true)
     260             :     {
     261          17 :         if (eGeomType == wkbPoint)
     262             :         {
     263           7 :             double dfId = 0.0;
     264           7 :             double dfX = 0.0;
     265           7 :             double dfY = 0.0;
     266           7 :             if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
     267          13 :                 VSIFReadL(&dfX, sizeof(double), 1, fp) != 1 ||
     268           6 :                 VSIFReadL(&dfY, sizeof(double), 1, fp) != 1)
     269             :             {
     270           4 :                 return nullptr;
     271             :             }
     272           6 :             CPL_LSBPTR64(&dfId);
     273           6 :             CPL_LSBPTR64(&dfX);
     274           6 :             CPL_LSBPTR64(&dfY);
     275             : 
     276           6 :             if (m_poFilterGeom != nullptr &&
     277           4 :                 (dfX < m_sFilterEnvelope.MinX || dfX > m_sFilterEnvelope.MaxX ||
     278           1 :                  dfY < m_sFilterEnvelope.MinY || dfY > m_sFilterEnvelope.MaxY))
     279             :             {
     280           3 :                 nNextFID++;
     281           3 :                 continue;
     282             :             }
     283             : 
     284           3 :             OGRPoint *poGeom = new OGRPoint(dfX, dfY);
     285           3 :             if (poSRS)
     286           3 :                 poGeom->assignSpatialReference(poSRS);
     287           3 :             OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     288           3 :             poFeature->SetField(0, dfId);
     289           3 :             poFeature->SetFID(nNextFID++);
     290           3 :             poFeature->SetGeometryDirectly(poGeom);
     291           3 :             ReadAVLLine(poFeature);
     292           3 :             return poFeature;
     293             :         }
     294          10 :         else if (eGeomType == wkbLineString)
     295             :         {
     296           5 :             double dfId = 0.0;
     297           5 :             double dfMinXShape = 0.0;
     298           5 :             double dfMaxXShape = 0.0;
     299           5 :             double dfMinYShape = 0.0;
     300           5 :             double dfMaxYShape = 0.0;
     301             : 
     302           5 :             if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
     303           4 :                 VSIFReadL(&dfMinXShape, sizeof(double), 1, fp) != 1 ||
     304           4 :                 VSIFReadL(&dfMaxXShape, sizeof(double), 1, fp) != 1 ||
     305          13 :                 VSIFReadL(&dfMinYShape, sizeof(double), 1, fp) != 1 ||
     306           4 :                 VSIFReadL(&dfMaxYShape, sizeof(double), 1, fp) != 1)
     307             :             {
     308           1 :                 bEOF = true;
     309           3 :                 return nullptr;
     310             :             }
     311           4 :             CPL_LSBPTR64(&dfId);
     312           4 :             CPL_LSBPTR64(&dfMinXShape);
     313           4 :             CPL_LSBPTR64(&dfMaxXShape);
     314           4 :             CPL_LSBPTR64(&dfMinYShape);
     315           4 :             CPL_LSBPTR64(&dfMaxYShape);
     316             : 
     317           4 :             unsigned int nNodes = 0;
     318           4 :             if (VSIFReadL(&nNodes, sizeof(unsigned int), 1, fp) != 1)
     319             :             {
     320           0 :                 bEOF = true;
     321           0 :                 return nullptr;
     322             :             }
     323           4 :             CPL_LSBPTR32(&nNodes);
     324             : 
     325           4 :             if (nNodes > 100 * 1000 * 1000)
     326             :             {
     327           0 :                 bEOF = true;
     328           0 :                 return nullptr;
     329             :             }
     330             : 
     331           4 :             if (m_poFilterGeom != nullptr &&
     332           2 :                 (dfMaxXShape < m_sFilterEnvelope.MinX ||
     333           2 :                  dfMinXShape > m_sFilterEnvelope.MaxX ||
     334           0 :                  dfMaxYShape < m_sFilterEnvelope.MinY ||
     335           0 :                  dfMinYShape > m_sFilterEnvelope.MaxY))
     336             :             {
     337           2 :                 nNextFID++;
     338           2 :                 VSIFSeekL(
     339           2 :                     fp, static_cast<vsi_l_offset>(sizeof(OGRRawPoint)) * nNodes,
     340             :                     SEEK_CUR);
     341           2 :                 continue;
     342             :             }
     343             : 
     344             :             OGRRawPoint *poRawPoints = static_cast<OGRRawPoint *>(
     345           2 :                 VSI_MALLOC2_VERBOSE(sizeof(OGRRawPoint), nNodes));
     346           2 :             if (poRawPoints == nullptr)
     347             :             {
     348           0 :                 bEOF = true;
     349           0 :                 return nullptr;
     350             :             }
     351             : 
     352           2 :             if (static_cast<unsigned int>(VSIFReadL(
     353           2 :                     poRawPoints, sizeof(OGRRawPoint), nNodes, fp)) != nNodes)
     354             :             {
     355           0 :                 VSIFree(poRawPoints);
     356           0 :                 bEOF = true;
     357           0 :                 return nullptr;
     358             :             }
     359             : 
     360             : #if defined(CPL_MSB)
     361             :             for (unsigned int iNode = 0; iNode < nNodes; iNode++)
     362             :             {
     363             :                 CPL_LSBPTR64(&poRawPoints[iNode].x);
     364             :                 CPL_LSBPTR64(&poRawPoints[iNode].y);
     365             :             }
     366             : #endif
     367             : 
     368           2 :             OGRLineString *poGeom = new OGRLineString();
     369           2 :             poGeom->setPoints(nNodes, poRawPoints, nullptr);
     370             : 
     371           2 :             VSIFree(poRawPoints);
     372             : 
     373           2 :             if (poSRS)
     374           2 :                 poGeom->assignSpatialReference(poSRS);
     375           2 :             OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     376           2 :             poFeature->SetField(0, dfId);
     377           2 :             poFeature->SetFID(nNextFID++);
     378           2 :             poFeature->SetGeometryDirectly(poGeom);
     379           2 :             ReadAVLLine(poFeature);
     380           2 :             return poFeature;
     381             :         }
     382             :         else  // if (eGeomType == wkbPolygon)
     383             :         {
     384           5 :             double dfId = 0.0;
     385           5 :             double dfMinXShape = 0.0;
     386           5 :             double dfMaxXShape = 0.0;
     387           5 :             double dfMinYShape = 0.0;
     388           5 :             double dfMaxYShape = 0.0;
     389             : 
     390           5 :             if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
     391           4 :                 VSIFReadL(&dfMinXShape, sizeof(double), 1, fp) != 1 ||
     392           4 :                 VSIFReadL(&dfMaxXShape, sizeof(double), 1, fp) != 1 ||
     393          13 :                 VSIFReadL(&dfMinYShape, sizeof(double), 1, fp) != 1 ||
     394           4 :                 VSIFReadL(&dfMaxYShape, sizeof(double), 1, fp) != 1)
     395             :             {
     396           1 :                 bEOF = true;
     397           3 :                 return nullptr;
     398             :             }
     399           4 :             CPL_LSBPTR64(&dfId);
     400           4 :             CPL_LSBPTR64(&dfMinXShape);
     401           4 :             CPL_LSBPTR64(&dfMaxXShape);
     402           4 :             CPL_LSBPTR64(&dfMinYShape);
     403           4 :             CPL_LSBPTR64(&dfMaxYShape);
     404           4 :             unsigned int nParts = 0;
     405           4 :             unsigned int nTotalNodes = 0;
     406           8 :             if (VSIFReadL(&nParts, sizeof(unsigned int), 1, fp) != 1 ||
     407           4 :                 VSIFReadL(&nTotalNodes, sizeof(unsigned int), 1, fp) != 1)
     408             :             {
     409           0 :                 bEOF = true;
     410           0 :                 return nullptr;
     411             :             }
     412           4 :             CPL_LSBPTR32(&nParts);
     413           4 :             CPL_LSBPTR32(&nTotalNodes);
     414             : 
     415           4 :             if (nParts > 100000 || nTotalNodes > 100 * 1000 * 1000)
     416             :             {
     417           0 :                 bEOF = true;
     418           0 :                 return nullptr;
     419             :             }
     420             : 
     421           4 :             if (m_poFilterGeom != nullptr &&
     422           2 :                 (dfMaxXShape < m_sFilterEnvelope.MinX ||
     423           2 :                  dfMinXShape > m_sFilterEnvelope.MaxX ||
     424           0 :                  dfMaxYShape < m_sFilterEnvelope.MinY ||
     425           0 :                  dfMinYShape > m_sFilterEnvelope.MaxY))
     426             :             {
     427           2 :                 VSIFSeekL(fp,
     428             :                           static_cast<vsi_l_offset>(sizeof(unsigned int)) *
     429           2 :                                   nParts +
     430             :                               static_cast<vsi_l_offset>(sizeof(OGRRawPoint)) *
     431           2 :                                   nTotalNodes,
     432             :                           SEEK_CUR);
     433           2 :                 nNextFID++;
     434           2 :                 continue;
     435             :             }
     436             : 
     437             :             OGRRawPoint *poRawPoints = static_cast<OGRRawPoint *>(
     438           2 :                 VSI_MALLOC2_VERBOSE(sizeof(OGRRawPoint), nTotalNodes));
     439           2 :             if (poRawPoints == nullptr)
     440             :             {
     441           0 :                 bEOF = true;
     442           0 :                 return nullptr;
     443             :             }
     444           2 :             unsigned int *panNodesCount = nullptr;
     445           2 :             if (nParts > 1)
     446             :             {
     447             :                 panNodesCount = static_cast<unsigned int *>(
     448           1 :                     CPLMalloc(sizeof(unsigned int) * nParts));
     449           1 :                 if (VSIFReadL(panNodesCount, sizeof(unsigned int) * nParts, 1,
     450           1 :                               fp) != 1)
     451             :                 {
     452           0 :                     VSIFree(poRawPoints);
     453           0 :                     VSIFree(panNodesCount);
     454           0 :                     bEOF = true;
     455           0 :                     return nullptr;
     456             :                 }
     457             : #if defined(CPL_MSB)
     458             :                 for (unsigned int iPart = 0; iPart < nParts; iPart++)
     459             :                 {
     460             :                     CPL_LSBPTR32(&panNodesCount[iPart]);
     461             :                 }
     462             : #endif
     463             :             }
     464             :             else
     465             :             {
     466           1 :                 unsigned int nNodes = 0;
     467           1 :                 if (VSIFReadL(&nNodes, sizeof(unsigned int) * nParts, 1, fp) !=
     468             :                     1)
     469             :                 {
     470           0 :                     VSIFree(poRawPoints);
     471           0 :                     bEOF = true;
     472           0 :                     return nullptr;
     473             :                 }
     474           1 :                 CPL_LSBPTR32(&nNodes);
     475           1 :                 if (nNodes != nTotalNodes)
     476             :                 {
     477           0 :                     VSIFree(poRawPoints);
     478           0 :                     bEOF = true;
     479           0 :                     return nullptr;
     480             :                 }
     481             :             }
     482             : 
     483           2 :             OGRPolygon *poGeom = new OGRPolygon();
     484           5 :             for (unsigned int iPart = 0; iPart < nParts; iPart++)
     485             :             {
     486           3 :                 unsigned int nNodes =
     487           3 :                     (nParts > 1) ? panNodesCount[iPart] : nTotalNodes;
     488           6 :                 if (nNodes > nTotalNodes ||
     489           3 :                     static_cast<unsigned int>(VSIFReadL(poRawPoints,
     490             :                                                         sizeof(OGRRawPoint),
     491           3 :                                                         nNodes, fp)) != nNodes)
     492             :                 {
     493           0 :                     VSIFree(poRawPoints);
     494           0 :                     VSIFree(panNodesCount);
     495           0 :                     delete poGeom;
     496           0 :                     bEOF = true;
     497           0 :                     return nullptr;
     498             :                 }
     499             : 
     500             : #if defined(CPL_MSB)
     501             :                 for (unsigned int iNode = 0; iNode < nNodes; iNode++)
     502             :                 {
     503             :                     CPL_LSBPTR64(&poRawPoints[iNode].x);
     504             :                     CPL_LSBPTR64(&poRawPoints[iNode].y);
     505             :                 }
     506             : #endif
     507             : 
     508           3 :                 OGRLinearRing *poLR = new OGRLinearRing();
     509           3 :                 poGeom->addRingDirectly(poLR);
     510           3 :                 poLR->setPoints(nNodes, poRawPoints, nullptr);
     511             :             }
     512             : 
     513           2 :             VSIFree(poRawPoints);
     514           2 :             VSIFree(panNodesCount);
     515             : 
     516           2 :             if (poSRS)
     517           2 :                 poGeom->assignSpatialReference(poSRS);
     518           2 :             OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     519           2 :             poFeature->SetField(0, dfId);
     520           2 :             poFeature->SetFID(nNextFID++);
     521           2 :             poFeature->SetGeometryDirectly(poGeom);
     522           2 :             ReadAVLLine(poFeature);
     523           2 :             return poFeature;
     524             :         }
     525           7 :     }
     526             : }
     527             : 
     528             : /************************************************************************/
     529             : /*                            ReadAVLLine()                             */
     530             : /************************************************************************/
     531             : 
     532           7 : void OGRIdrisiLayer::ReadAVLLine(OGRFeature *poFeature)
     533             : {
     534           7 :     if (fpAVL == nullptr)
     535           4 :         return;
     536             : 
     537           3 :     const char *pszLine = CPLReadLineL(fpAVL);
     538           3 :     if (pszLine == nullptr)
     539           0 :         return;
     540             : 
     541           3 :     char **papszTokens = CSLTokenizeStringComplex(pszLine, "\t", TRUE, TRUE);
     542           3 :     if (CSLCount(papszTokens) == poFeatureDefn->GetFieldCount())
     543             :     {
     544           3 :         const int nID = atoi(papszTokens[0]);
     545           3 :         if (nID == poFeature->GetFID())
     546             :         {
     547           8 :             for (int i = 1; i < poFeatureDefn->GetFieldCount(); i++)
     548             :             {
     549           6 :                 poFeature->SetField(i, papszTokens[i]);
     550             :             }
     551             :         }
     552             :     }
     553           3 :     CSLDestroy(papszTokens);
     554             : }
     555             : 
     556             : /************************************************************************/
     557             : /*                             SetExtent()                              */
     558             : /************************************************************************/
     559             : 
     560           3 : void OGRIdrisiLayer::SetExtent(double dfMinXIn, double dfMinYIn,
     561             :                                double dfMaxXIn, double dfMaxYIn)
     562             : {
     563           3 :     bExtentValid = true;
     564           3 :     dfMinX = dfMinXIn;
     565           3 :     dfMinY = dfMinYIn;
     566           3 :     dfMaxX = dfMaxXIn;
     567           3 :     dfMaxY = dfMaxYIn;
     568           3 : }
     569             : 
     570             : /************************************************************************/
     571             : /*                            IGetExtent()                              */
     572             : /************************************************************************/
     573             : 
     574           3 : OGRErr OGRIdrisiLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
     575             :                                   bool bForce)
     576             : {
     577           3 :     if (!bExtentValid)
     578           0 :         return OGRLayer::IGetExtent(iGeomField, psExtent, bForce);
     579             : 
     580           3 :     psExtent->MinX = dfMinX;
     581           3 :     psExtent->MinY = dfMinY;
     582           3 :     psExtent->MaxX = dfMaxX;
     583           3 :     psExtent->MaxY = dfMaxY;
     584           3 :     return OGRERR_NONE;
     585             : }
     586             : 
     587             : /************************************************************************/
     588             : /*                          GetFeatureCount()                           */
     589             : /************************************************************************/
     590             : 
     591           3 : GIntBig OGRIdrisiLayer::GetFeatureCount(int bForce)
     592             : {
     593           3 :     if (nTotalFeatures > 0 && m_poFilterGeom == nullptr &&
     594           3 :         m_poAttrQuery == nullptr)
     595           3 :         return nTotalFeatures;
     596             : 
     597           0 :     return OGRLayer::GetFeatureCount(bForce);
     598             : }

Generated by: LCOV version 1.14