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

Generated by: LCOV version 1.14