LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/idrisi - ogridrisilayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 261 319 81.8 %
Date: 2024-11-21 22:18:42 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           3 :     const char *pszADCFilename = CPLResetExtension(pszFilename, "adc");
      93           3 :     VSILFILE *fpADC = VSIFOpenL(pszADCFilename, "rb");
      94           3 :     if (fpADC == nullptr)
      95             :     {
      96           2 :         pszADCFilename = CPLResetExtension(pszFilename, "ADC");
      97           2 :         fpADC = VSIFOpenL(pszADCFilename, "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(pszADCFilename, 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           1 :     const char *pszAVLFilename = CPLResetExtension(pszFilename, "avl");
     154           1 :     fpAVL = VSIFOpenL(pszAVLFilename, "rb");
     155           1 :     if (fpAVL == nullptr)
     156             :     {
     157           0 :         pszAVLFilename = CPLResetExtension(pszFilename, "AVL");
     158           0 :         fpAVL = VSIFOpenL(pszAVLFilename, "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)
     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(fp, sizeof(OGRRawPoint) * nNodes, SEEK_CUR);
     339           2 :                 continue;
     340             :             }
     341             : 
     342             :             OGRRawPoint *poRawPoints = static_cast<OGRRawPoint *>(
     343           2 :                 VSI_MALLOC2_VERBOSE(sizeof(OGRRawPoint), nNodes));
     344           2 :             if (poRawPoints == nullptr)
     345             :             {
     346           0 :                 bEOF = true;
     347           0 :                 return nullptr;
     348             :             }
     349             : 
     350           2 :             if (static_cast<unsigned int>(VSIFReadL(
     351           2 :                     poRawPoints, sizeof(OGRRawPoint), nNodes, fp)) != nNodes)
     352             :             {
     353           0 :                 VSIFree(poRawPoints);
     354           0 :                 bEOF = true;
     355           0 :                 return nullptr;
     356             :             }
     357             : 
     358             : #if defined(CPL_MSB)
     359             :             for (unsigned int iNode = 0; iNode < nNodes; iNode++)
     360             :             {
     361             :                 CPL_LSBPTR64(&poRawPoints[iNode].x);
     362             :                 CPL_LSBPTR64(&poRawPoints[iNode].y);
     363             :             }
     364             : #endif
     365             : 
     366           2 :             OGRLineString *poGeom = new OGRLineString();
     367           2 :             poGeom->setPoints(nNodes, poRawPoints, nullptr);
     368             : 
     369           2 :             VSIFree(poRawPoints);
     370             : 
     371           2 :             if (poSRS)
     372           2 :                 poGeom->assignSpatialReference(poSRS);
     373           2 :             OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     374           2 :             poFeature->SetField(0, dfId);
     375           2 :             poFeature->SetFID(nNextFID++);
     376           2 :             poFeature->SetGeometryDirectly(poGeom);
     377           2 :             ReadAVLLine(poFeature);
     378           2 :             return poFeature;
     379             :         }
     380             :         else  // if (eGeomType == wkbPolygon)
     381             :         {
     382           5 :             double dfId = 0.0;
     383           5 :             double dfMinXShape = 0.0;
     384           5 :             double dfMaxXShape = 0.0;
     385           5 :             double dfMinYShape = 0.0;
     386           5 :             double dfMaxYShape = 0.0;
     387             : 
     388           5 :             if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
     389           4 :                 VSIFReadL(&dfMinXShape, sizeof(double), 1, fp) != 1 ||
     390           4 :                 VSIFReadL(&dfMaxXShape, sizeof(double), 1, fp) != 1 ||
     391          13 :                 VSIFReadL(&dfMinYShape, sizeof(double), 1, fp) != 1 ||
     392           4 :                 VSIFReadL(&dfMaxYShape, sizeof(double), 1, fp) != 1)
     393             :             {
     394           1 :                 bEOF = true;
     395           3 :                 return nullptr;
     396             :             }
     397           4 :             CPL_LSBPTR64(&dfId);
     398           4 :             CPL_LSBPTR64(&dfMinXShape);
     399           4 :             CPL_LSBPTR64(&dfMaxXShape);
     400           4 :             CPL_LSBPTR64(&dfMinYShape);
     401           4 :             CPL_LSBPTR64(&dfMaxYShape);
     402           4 :             unsigned int nParts = 0;
     403           4 :             unsigned int nTotalNodes = 0;
     404           8 :             if (VSIFReadL(&nParts, sizeof(unsigned int), 1, fp) != 1 ||
     405           4 :                 VSIFReadL(&nTotalNodes, sizeof(unsigned int), 1, fp) != 1)
     406             :             {
     407           0 :                 bEOF = true;
     408           0 :                 return nullptr;
     409             :             }
     410           4 :             CPL_LSBPTR32(&nParts);
     411           4 :             CPL_LSBPTR32(&nTotalNodes);
     412             : 
     413           4 :             if (nParts > 100000 || nTotalNodes > 100 * 1000 * 1000)
     414             :             {
     415           0 :                 bEOF = true;
     416           0 :                 return nullptr;
     417             :             }
     418             : 
     419           4 :             if (m_poFilterGeom != nullptr &&
     420           2 :                 (dfMaxXShape < m_sFilterEnvelope.MinX ||
     421           2 :                  dfMinXShape > m_sFilterEnvelope.MaxX ||
     422           0 :                  dfMaxYShape < m_sFilterEnvelope.MinY ||
     423           0 :                  dfMinYShape > m_sFilterEnvelope.MaxY))
     424             :             {
     425           2 :                 VSIFSeekL(fp,
     426           2 :                           sizeof(unsigned int) * nParts +
     427           2 :                               sizeof(OGRRawPoint) * nTotalNodes,
     428             :                           SEEK_CUR);
     429           2 :                 nNextFID++;
     430           2 :                 continue;
     431             :             }
     432             : 
     433             :             OGRRawPoint *poRawPoints = static_cast<OGRRawPoint *>(
     434           2 :                 VSI_MALLOC2_VERBOSE(sizeof(OGRRawPoint), nTotalNodes));
     435           2 :             if (poRawPoints == nullptr)
     436             :             {
     437           0 :                 bEOF = true;
     438           0 :                 return nullptr;
     439             :             }
     440           2 :             unsigned int *panNodesCount = nullptr;
     441           2 :             if (nParts > 1)
     442             :             {
     443             :                 panNodesCount = static_cast<unsigned int *>(
     444           1 :                     CPLMalloc(sizeof(unsigned int) * nParts));
     445           1 :                 if (VSIFReadL(panNodesCount, sizeof(unsigned int) * nParts, 1,
     446           1 :                               fp) != 1)
     447             :                 {
     448           0 :                     VSIFree(poRawPoints);
     449           0 :                     VSIFree(panNodesCount);
     450           0 :                     bEOF = true;
     451           0 :                     return nullptr;
     452             :                 }
     453             : #if defined(CPL_MSB)
     454             :                 for (unsigned int iPart = 0; iPart < nParts; iPart++)
     455             :                 {
     456             :                     CPL_LSBPTR32(&panNodesCount[iPart]);
     457             :                 }
     458             : #endif
     459             :             }
     460             :             else
     461             :             {
     462           1 :                 unsigned int nNodes = 0;
     463           1 :                 if (VSIFReadL(&nNodes, sizeof(unsigned int) * nParts, 1, fp) !=
     464             :                     1)
     465             :                 {
     466           0 :                     VSIFree(poRawPoints);
     467           0 :                     bEOF = true;
     468           0 :                     return nullptr;
     469             :                 }
     470           1 :                 CPL_LSBPTR32(&nNodes);
     471           1 :                 if (nNodes != nTotalNodes)
     472             :                 {
     473           0 :                     VSIFree(poRawPoints);
     474           0 :                     bEOF = true;
     475           0 :                     return nullptr;
     476             :                 }
     477             :             }
     478             : 
     479           2 :             OGRPolygon *poGeom = new OGRPolygon();
     480           5 :             for (unsigned int iPart = 0; iPart < nParts; iPart++)
     481             :             {
     482           3 :                 unsigned int nNodes =
     483           3 :                     (nParts > 1) ? panNodesCount[iPart] : nTotalNodes;
     484           6 :                 if (nNodes > nTotalNodes ||
     485           3 :                     static_cast<unsigned int>(VSIFReadL(poRawPoints,
     486             :                                                         sizeof(OGRRawPoint),
     487           3 :                                                         nNodes, fp)) != nNodes)
     488             :                 {
     489           0 :                     VSIFree(poRawPoints);
     490           0 :                     VSIFree(panNodesCount);
     491           0 :                     delete poGeom;
     492           0 :                     bEOF = true;
     493           0 :                     return nullptr;
     494             :                 }
     495             : 
     496             : #if defined(CPL_MSB)
     497             :                 for (unsigned int iNode = 0; iNode < nNodes; iNode++)
     498             :                 {
     499             :                     CPL_LSBPTR64(&poRawPoints[iNode].x);
     500             :                     CPL_LSBPTR64(&poRawPoints[iNode].y);
     501             :                 }
     502             : #endif
     503             : 
     504           3 :                 OGRLinearRing *poLR = new OGRLinearRing();
     505           3 :                 poGeom->addRingDirectly(poLR);
     506           3 :                 poLR->setPoints(nNodes, poRawPoints, nullptr);
     507             :             }
     508             : 
     509           2 :             VSIFree(poRawPoints);
     510           2 :             VSIFree(panNodesCount);
     511             : 
     512           2 :             if (poSRS)
     513           2 :                 poGeom->assignSpatialReference(poSRS);
     514           2 :             OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     515           2 :             poFeature->SetField(0, dfId);
     516           2 :             poFeature->SetFID(nNextFID++);
     517           2 :             poFeature->SetGeometryDirectly(poGeom);
     518           2 :             ReadAVLLine(poFeature);
     519           2 :             return poFeature;
     520             :         }
     521           7 :     }
     522             : }
     523             : 
     524             : /************************************************************************/
     525             : /*                            ReadAVLLine()                             */
     526             : /************************************************************************/
     527             : 
     528           7 : void OGRIdrisiLayer::ReadAVLLine(OGRFeature *poFeature)
     529             : {
     530           7 :     if (fpAVL == nullptr)
     531           4 :         return;
     532             : 
     533           3 :     const char *pszLine = CPLReadLineL(fpAVL);
     534           3 :     if (pszLine == nullptr)
     535           0 :         return;
     536             : 
     537           3 :     char **papszTokens = CSLTokenizeStringComplex(pszLine, "\t", TRUE, TRUE);
     538           3 :     if (CSLCount(papszTokens) == poFeatureDefn->GetFieldCount())
     539             :     {
     540           3 :         const int nID = atoi(papszTokens[0]);
     541           3 :         if (nID == poFeature->GetFID())
     542             :         {
     543           8 :             for (int i = 1; i < poFeatureDefn->GetFieldCount(); i++)
     544             :             {
     545           6 :                 poFeature->SetField(i, papszTokens[i]);
     546             :             }
     547             :         }
     548             :     }
     549           3 :     CSLDestroy(papszTokens);
     550             : }
     551             : 
     552             : /************************************************************************/
     553             : /*                             SetExtent()                              */
     554             : /************************************************************************/
     555             : 
     556           3 : void OGRIdrisiLayer::SetExtent(double dfMinXIn, double dfMinYIn,
     557             :                                double dfMaxXIn, double dfMaxYIn)
     558             : {
     559           3 :     bExtentValid = true;
     560           3 :     dfMinX = dfMinXIn;
     561           3 :     dfMinY = dfMinYIn;
     562           3 :     dfMaxX = dfMaxXIn;
     563           3 :     dfMaxY = dfMaxYIn;
     564           3 : }
     565             : 
     566             : /************************************************************************/
     567             : /*                             GetExtent()                              */
     568             : /************************************************************************/
     569             : 
     570           3 : OGRErr OGRIdrisiLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     571             : {
     572           3 :     if (!bExtentValid)
     573           0 :         return OGRLayer::GetExtent(psExtent, bForce);
     574             : 
     575           3 :     psExtent->MinX = dfMinX;
     576           3 :     psExtent->MinY = dfMinY;
     577           3 :     psExtent->MaxX = dfMaxX;
     578           3 :     psExtent->MaxY = dfMaxY;
     579           3 :     return OGRERR_NONE;
     580             : }
     581             : 
     582             : /************************************************************************/
     583             : /*                          GetFeatureCount()                           */
     584             : /************************************************************************/
     585             : 
     586           3 : GIntBig OGRIdrisiLayer::GetFeatureCount(int bForce)
     587             : {
     588           3 :     if (nTotalFeatures > 0 && m_poFilterGeom == nullptr &&
     589           3 :         m_poAttrQuery == nullptr)
     590           3 :         return nTotalFeatures;
     591             : 
     592           0 :     return OGRLayer::GetFeatureCount(bForce);
     593             : }

Generated by: LCOV version 1.14