LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/pds - ogrpdslayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 286 456 62.7 %
Date: 2024-11-21 22:18:42 Functions: 9 10 90.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  PDS Translator
       4             :  * Purpose:  Implements OGRPDSLayer class.
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "ogr_pds.h"
      14             : #include "cpl_conv.h"
      15             : #include "cpl_string.h"
      16             : #include "ogr_p.h"
      17             : #include "cpl_safemaths.hpp"
      18             : 
      19             : #include <algorithm>
      20             : 
      21             : namespace OGRPDS
      22             : {
      23             : 
      24             : /************************************************************************/
      25             : /*                           OGRPDSLayer()                              */
      26             : /************************************************************************/
      27             : 
      28           2 : OGRPDSLayer::OGRPDSLayer(const std::string &osTableIDIn,
      29             :                          const char *pszLayerName, VSILFILE *fp,
      30             :                          const std::string &osLabelFilename,
      31             :                          const std::string &osStructureFilename, int nRecordsIn,
      32             :                          int nStartBytesIn, int nRecordSizeIn,
      33           2 :                          GByte *pabyRecordIn, bool bIsASCII)
      34           2 :     : poFeatureDefn(new OGRFeatureDefn(pszLayerName)), osTableID(osTableIDIn),
      35             :       fpPDS(fp), nRecords(nRecordsIn), nStartBytes(nStartBytesIn),
      36             :       nRecordSize(nRecordSizeIn), pabyRecord(pabyRecordIn), nNextFID(0),
      37           4 :       nLongitudeIndex(-1), nLatitudeIndex(-1), pasFieldDesc(nullptr)
      38             : {
      39           2 :     SetDescription(poFeatureDefn->GetName());
      40           2 :     poFeatureDefn->Reference();
      41           2 :     poFeatureDefn->SetGeomType(wkbNone);
      42             : 
      43           2 :     if (!osStructureFilename.empty())
      44             :     {
      45           2 :         ReadStructure(osStructureFilename);
      46             :     }
      47             :     else
      48             :     {
      49           0 :         ReadStructure(osLabelFilename);
      50             :     }
      51             : 
      52           2 :     if (bIsASCII && poFeatureDefn->GetFieldCount() == 0)
      53             :     {
      54           0 :         VSIFSeekL(fpPDS, nStartBytes, SEEK_SET);
      55           0 :         VSIFReadL(pabyRecord, nRecordSize, 1, fpPDS);
      56             : 
      57           0 :         char **papszTokens = CSLTokenizeString2((const char *)pabyRecord, " ",
      58             :                                                 CSLT_HONOURSTRINGS);
      59           0 :         const int nTokens = CSLCount(papszTokens);
      60           0 :         for (int i = 0; i < nTokens; i++)
      61             :         {
      62           0 :             const char *pszStr = papszTokens[i];
      63           0 :             char ch = '\0';
      64           0 :             OGRFieldType eFieldType = OFTInteger;
      65           0 :             while ((ch = *pszStr) != 0)
      66             :             {
      67           0 :                 if ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-')
      68             :                 {
      69             :                 }
      70           0 :                 else if (ch == '.')
      71             :                 {
      72           0 :                     eFieldType = OFTReal;
      73             :                 }
      74             :                 else
      75             :                 {
      76           0 :                     eFieldType = OFTString;
      77           0 :                     break;
      78             :                 }
      79           0 :                 pszStr++;
      80             :             }
      81             :             char szFieldName[32];
      82           0 :             snprintf(szFieldName, sizeof(szFieldName), "field_%d",
      83           0 :                      poFeatureDefn->GetFieldCount() + 1);
      84           0 :             OGRFieldDefn oFieldDefn(szFieldName, eFieldType);
      85           0 :             poFeatureDefn->AddFieldDefn(&oFieldDefn);
      86             :         }
      87           0 :         CSLDestroy(papszTokens);
      88             :     }
      89             : 
      90           2 :     if (nLongitudeIndex >= 0 && nLatitudeIndex >= 0)
      91             :     {
      92           1 :         poFeatureDefn->SetGeomType(wkbPoint);
      93             :     }
      94             : 
      95           2 :     OGRPDSLayer::ResetReading();
      96           2 : }
      97             : 
      98             : /************************************************************************/
      99             : /*                             ~OGRPDSLayer()                           */
     100             : /************************************************************************/
     101             : 
     102           4 : OGRPDSLayer::~OGRPDSLayer()
     103             : 
     104             : {
     105           2 :     CPLFree(pasFieldDesc);
     106           2 :     poFeatureDefn->Release();
     107           2 :     VSIFree(pabyRecord);
     108             : 
     109           2 :     VSIFCloseL(fpPDS);
     110           4 : }
     111             : 
     112             : /************************************************************************/
     113             : /*                           ReadStructure()                            */
     114             : /************************************************************************/
     115             : 
     116           2 : void OGRPDSLayer::ReadStructure(const std::string &osStructureFilename)
     117             : 
     118             : {
     119           2 :     VSILFILE *fpStructure = VSIFOpenL(osStructureFilename.c_str(), "rb");
     120           2 :     if (fpStructure == nullptr)
     121           0 :         return;
     122             : 
     123           2 :     int nFields = 0;
     124           2 :     bool bInObjectColumn = false;
     125           2 :     int nExpectedColumnNumber = 0;
     126           4 :     CPLString osColumnName;
     127           4 :     CPLString osColumnDataType;
     128           4 :     CPLString osColumnStartByte;
     129           4 :     CPLString osColumnBytes;
     130           4 :     CPLString osColumnFormat;
     131           4 :     CPLString osColumnUnit;
     132           4 :     CPLString osColumnItems;
     133           4 :     CPLString osColumnItemBytes;
     134           2 :     int nRowBytes = nRecordSize;
     135             :     while (true)
     136             :     {
     137         871 :         CPLPushErrorHandler(CPLQuietErrorHandler);
     138         871 :         const char *pszLine = CPLReadLine2L(fpStructure, 256, nullptr);
     139         871 :         CPLPopErrorHandler();
     140         871 :         CPLErrorReset();
     141         871 :         if (pszLine == nullptr)
     142           2 :             break;
     143             : 
     144             :         char **papszTokens =
     145         869 :             CSLTokenizeString2(pszLine, " =", CSLT_HONOURSTRINGS);
     146         869 :         const int nTokens = CSLCount(papszTokens);
     147             : 
     148         869 :         if (bInObjectColumn && nTokens >= 1 &&
     149         723 :             EQUAL(papszTokens[0], "END_OBJECT"))
     150             :         {
     151         116 :             if (!osColumnName.empty() && !osColumnDataType.empty() &&
     152         116 :                 !osColumnStartByte.empty() && !osColumnBytes.empty())
     153             :             {
     154         116 :                 pasFieldDesc = static_cast<FieldDesc *>(CPLRealloc(
     155          58 :                     pasFieldDesc, (nFields + 1) * sizeof(FieldDesc)));
     156          58 :                 pasFieldDesc[nFields].nStartByte = atoi(osColumnStartByte) - 1;
     157          58 :                 pasFieldDesc[nFields].nByteCount = atoi(osColumnBytes);
     158          58 :                 if (pasFieldDesc[nFields].nStartByte >= 0 &&
     159          58 :                     pasFieldDesc[nFields].nByteCount > 0 &&
     160          58 :                     pasFieldDesc[nFields].nStartByte <
     161          58 :                         INT_MAX - pasFieldDesc[nFields].nByteCount &&
     162          58 :                     pasFieldDesc[nFields].nStartByte +
     163          58 :                             pasFieldDesc[nFields].nByteCount <=
     164          58 :                         nRecordSize)
     165             :                 {
     166          58 :                     OGRFieldType eFieldType = OFTString;
     167          58 :                     OGRFieldSubType eSubType = OFSTNone;
     168          58 :                     pasFieldDesc[nFields].eFormat = CHARACTER;
     169          58 :                     pasFieldDesc[nFields].nItemBytes = atoi(osColumnItemBytes);
     170          58 :                     pasFieldDesc[nFields].nItems = atoi(osColumnItems);
     171          58 :                     if (pasFieldDesc[nFields].nItems == 0)
     172          51 :                         pasFieldDesc[nFields].nItems = 1;
     173          58 :                     if (pasFieldDesc[nFields].nItemBytes == 0 &&
     174          51 :                         pasFieldDesc[nFields].nItems == 1)
     175          51 :                         pasFieldDesc[nFields].nItemBytes =
     176          51 :                             pasFieldDesc[nFields].nByteCount;
     177             : 
     178          58 :                     if (osColumnDataType.compare("ASCII_REAL") == 0)
     179             :                     {
     180          14 :                         eFieldType = OFTReal;
     181          14 :                         pasFieldDesc[nFields].eFormat = ASCII_REAL;
     182             :                     }
     183          44 :                     else if (osColumnDataType.compare("ASCII_INTEGER") == 0)
     184             :                     {
     185          11 :                         eFieldType = OFTInteger;
     186          11 :                         pasFieldDesc[nFields].eFormat = ASCII_INTEGER;
     187             :                     }
     188          33 :                     else if (osColumnDataType.compare("MSB_UNSIGNED_INTEGER") ==
     189             :                              0)
     190             :                     {
     191          11 :                         if (pasFieldDesc[nFields].nItemBytes == 1 ||
     192          11 :                             pasFieldDesc[nFields].nItemBytes == 2)
     193             :                         {
     194           9 :                             if (pasFieldDesc[nFields].nItems > 1)
     195           0 :                                 eFieldType = OFTIntegerList;
     196             :                             else
     197           9 :                                 eFieldType = OFTInteger;
     198             :                         }
     199             :                         else
     200             :                         {
     201           2 :                             pasFieldDesc[nFields].nItemBytes = 4;
     202           2 :                             if (pasFieldDesc[nFields].nItems > 1)
     203           0 :                                 eFieldType = OFTRealList;
     204             :                             else
     205           2 :                                 eFieldType = OFTReal;
     206             :                         }
     207          11 :                         pasFieldDesc[nFields].eFormat = MSB_UNSIGNED_INTEGER;
     208             :                     }
     209          22 :                     else if (osColumnDataType.compare("MSB_INTEGER") == 0)
     210             :                     {
     211           4 :                         if (pasFieldDesc[nFields].nItemBytes != 1 &&
     212           4 :                             pasFieldDesc[nFields].nItemBytes != 2)
     213           4 :                             pasFieldDesc[nFields].nItemBytes = 4;
     214           4 :                         if (pasFieldDesc[nFields].nItems > 1)
     215           0 :                             eFieldType = OFTIntegerList;
     216             :                         else
     217           4 :                             eFieldType = OFTInteger;
     218           4 :                         pasFieldDesc[nFields].eFormat = MSB_INTEGER;
     219             :                     }
     220          18 :                     else if (osColumnDataType.compare("IEEE_REAL") == 0)
     221             :                     {
     222          16 :                         if (pasFieldDesc[nFields].nItemBytes == 4)
     223             :                         {
     224           8 :                             eSubType = OFSTFloat32;
     225             :                         }
     226           8 :                         else if (pasFieldDesc[nFields].nItemBytes != 8)
     227             :                         {
     228             :                             // Not sure if this is correct, but default to
     229             :                             // Float32
     230           0 :                             pasFieldDesc[nFields].nItemBytes = 4;
     231             :                         }
     232          16 :                         if (pasFieldDesc[nFields].nItems > 1)
     233           7 :                             eFieldType = OFTRealList;
     234             :                         else
     235           9 :                             eFieldType = OFTReal;
     236          16 :                         pasFieldDesc[nFields].eFormat = IEEE_REAL;
     237             :                     }
     238             : 
     239          58 :                     OGRFieldDefn oFieldDefn(osColumnName, eFieldType);
     240         130 :                     if ((pasFieldDesc[nFields].eFormat == ASCII_REAL &&
     241         102 :                          !osColumnFormat.empty() && osColumnFormat[0] == 'F') ||
     242          44 :                         (pasFieldDesc[nFields].eFormat == ASCII_INTEGER &&
     243          11 :                          !osColumnFormat.empty() && osColumnFormat[0] == 'I'))
     244             :                     {
     245          25 :                         const char *pszFormat = osColumnFormat.c_str();
     246          25 :                         int nWidth = atoi(pszFormat + 1);
     247          25 :                         oFieldDefn.SetWidth(nWidth);
     248          25 :                         const char *pszPoint = strchr(pszFormat, '.');
     249          25 :                         if (pszPoint)
     250             :                         {
     251          14 :                             int nPrecision = atoi(pszPoint + 1);
     252          14 :                             oFieldDefn.SetPrecision(nPrecision);
     253             :                         }
     254             :                     }
     255          33 :                     else if (oFieldDefn.GetType() == OFTString &&
     256          33 :                              !osColumnFormat.empty() &&
     257           0 :                              osColumnFormat[0] == 'A')
     258             :                     {
     259           0 :                         const char *pszFormat = osColumnFormat.c_str();
     260           0 :                         int nWidth = atoi(pszFormat + 1);
     261           0 :                         oFieldDefn.SetWidth(nWidth);
     262             :                     }
     263          58 :                     oFieldDefn.SetSubType(eSubType);
     264          58 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
     265             : 
     266          83 :                     if (oFieldDefn.GetType() == OFTReal &&
     267          25 :                         osColumnUnit.compare("DEGREE") == 0)
     268             :                     {
     269           7 :                         if (osColumnName.compare("LONGITUDE") == 0)
     270           1 :                             nLongitudeIndex = nFields;
     271           6 :                         else if (osColumnName.compare("LATITUDE") == 0)
     272           1 :                             nLatitudeIndex = nFields;
     273             :                     }
     274             : 
     275          58 :                     nFields++;
     276             :                 }
     277             :                 else
     278             :                 {
     279           0 :                     CPLError(CE_Failure, CPLE_AppDefined,
     280             :                              "Field %d out of record extents", nFields);
     281           0 :                     CSLDestroy(papszTokens);
     282           0 :                     if (nFields == 0)
     283             :                     {
     284           0 :                         CPLFree(pasFieldDesc);
     285           0 :                         pasFieldDesc = nullptr;
     286             :                     }
     287           0 :                     break;
     288             :                 }
     289             :             }
     290             :             else
     291             :             {
     292           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     293             :                          "Did not get expected records for field %d", nFields);
     294           0 :                 CSLDestroy(papszTokens);
     295           0 :                 break;
     296             :             }
     297          58 :             bInObjectColumn = false;
     298             :         }
     299         811 :         else if (nTokens == 2)
     300             :         {
     301         490 :             if (EQUAL(papszTokens[0], "PDS_VERSION_ID"))
     302             :             {
     303           0 :                 CSLDestroy(papszTokens);
     304           0 :                 papszTokens = nullptr;
     305             :                 while (true)
     306             :                 {
     307           0 :                     CPLPushErrorHandler(CPLQuietErrorHandler);
     308           0 :                     pszLine = CPLReadLine2L(fpStructure, 256, nullptr);
     309           0 :                     CPLPopErrorHandler();
     310           0 :                     CPLErrorReset();
     311           0 :                     if (pszLine == nullptr)
     312           0 :                         break;
     313             :                     papszTokens =
     314           0 :                         CSLTokenizeString2(pszLine, " =", CSLT_HONOURSTRINGS);
     315           0 :                     int nTokens2 = CSLCount(papszTokens);
     316           0 :                     if (nTokens2 == 2 && EQUAL(papszTokens[0], "OBJECT") &&
     317           0 :                         EQUAL(papszTokens[1], osTableID.c_str()))
     318             :                     {
     319           0 :                         break;
     320             :                     }
     321           0 :                     CSLDestroy(papszTokens);
     322           0 :                     papszTokens = nullptr;
     323           0 :                 }
     324           0 :                 CSLDestroy(papszTokens);
     325           0 :                 papszTokens = nullptr;
     326           0 :                 if (pszLine == nullptr)
     327           0 :                     break;
     328             :             }
     329         490 :             else if (EQUAL(papszTokens[0], "ROW_BYTES"))
     330             :             {
     331           1 :                 nRowBytes = atoi(papszTokens[1]);
     332           1 :                 if (nRowBytes < 0 || nRowBytes > 10 * 1024 * 1024)
     333             :                 {
     334           0 :                     CPLError(CE_Failure, CPLE_NotSupported,
     335             :                              "Invalid value of ROW_BYTES");
     336           0 :                     CSLDestroy(papszTokens);
     337           0 :                     break;
     338             :                 }
     339             :             }
     340         489 :             else if (EQUAL(papszTokens[0], "ROW_SUFFIX_BYTES"))
     341             :             {
     342             :                 try
     343             :                 {
     344             :                     nRowBytes =
     345           0 :                         (CPLSM(nRowBytes) + CPLSM(atoi(papszTokens[1]))).v();
     346             :                 }
     347           0 :                 catch (const CPLSafeIntOverflow &)
     348             :                 {
     349           0 :                     CPLError(CE_Failure, CPLE_NotSupported,
     350             :                              "Invalid value of ROW_SUFFIX_BYTES");
     351           0 :                     CSLDestroy(papszTokens);
     352           0 :                     break;
     353             :                 }
     354           0 :                 if (nRowBytes < 0 || nRowBytes > 10 * 1024 * 1024)
     355             :                 {
     356           0 :                     CPLError(CE_Failure, CPLE_NotSupported,
     357             :                              "Invalid value of ROW_SUFFIX_BYTES");
     358           0 :                     CSLDestroy(papszTokens);
     359           0 :                     break;
     360             :                 }
     361             :             }
     362         489 :             else if (EQUAL(papszTokens[0], "OBJECT") &&
     363          58 :                      EQUAL(papszTokens[1], "COLUMN"))
     364             :             {
     365          58 :                 if (nRowBytes > nRecordSize)
     366             :                 {
     367           0 :                     nRecordSize = nRowBytes;
     368           0 :                     VSIFree(pabyRecord);
     369           0 :                     pabyRecord = (GByte *)CPLMalloc(nRecordSize + 1);
     370           0 :                     pabyRecord[nRecordSize] = 0;
     371             :                 }
     372             :                 else
     373          58 :                     nRecordSize = nRowBytes;
     374             : 
     375          58 :                 nExpectedColumnNumber++;
     376          58 :                 bInObjectColumn = true;
     377          58 :                 osColumnName = "";
     378          58 :                 osColumnDataType = "";
     379          58 :                 osColumnStartByte = "";
     380          58 :                 osColumnBytes = "";
     381          58 :                 osColumnItems = "";
     382          58 :                 osColumnItemBytes = "";
     383          58 :                 osColumnFormat = "";
     384          58 :                 osColumnUnit = "";
     385             :             }
     386         431 :             else if (bInObjectColumn && EQUAL(papszTokens[0], "COLUMN_NUMBER"))
     387             :             {
     388          58 :                 int nColumnNumber = atoi(papszTokens[1]);
     389          58 :                 if (nColumnNumber != nExpectedColumnNumber)
     390             :                 {
     391           0 :                     CPLError(CE_Failure, CPLE_AppDefined,
     392             :                              "Did not get expected column number");
     393           0 :                     CSLDestroy(papszTokens);
     394           0 :                     break;
     395          58 :                 }
     396             :             }
     397         373 :             else if (bInObjectColumn && EQUAL(papszTokens[0], "NAME"))
     398             :             {
     399          58 :                 osColumnName = "\"";
     400          58 :                 osColumnName += papszTokens[1];
     401          58 :                 osColumnName += "\"";
     402          58 :                 OGRPDSDataSource::CleanString(osColumnName);
     403             :             }
     404         315 :             else if (bInObjectColumn && EQUAL(papszTokens[0], "DATA_TYPE"))
     405             :             {
     406          58 :                 osColumnDataType = papszTokens[1];
     407          58 :                 OGRPDSDataSource::CleanString(osColumnDataType);
     408             :             }
     409         257 :             else if (bInObjectColumn && EQUAL(papszTokens[0], "START_BYTE"))
     410             :             {
     411          58 :                 osColumnStartByte = papszTokens[1];
     412             :             }
     413         199 :             else if (bInObjectColumn && EQUAL(papszTokens[0], "BYTES"))
     414             :             {
     415          58 :                 osColumnBytes = papszTokens[1];
     416             :             }
     417         141 :             else if (bInObjectColumn && EQUAL(papszTokens[0], "ITEMS"))
     418             :             {
     419           7 :                 osColumnItems = papszTokens[1];
     420             :             }
     421         134 :             else if (bInObjectColumn && EQUAL(papszTokens[0], "ITEM_BYTES"))
     422             :             {
     423           7 :                 osColumnItemBytes = papszTokens[1];
     424             :             }
     425         127 :             else if (bInObjectColumn && EQUAL(papszTokens[0], "FORMAT"))
     426             :             {
     427          25 :                 osColumnFormat = papszTokens[1];
     428             :             }
     429         102 :             else if (bInObjectColumn && EQUAL(papszTokens[0], "UNIT"))
     430             :             {
     431          11 :                 osColumnUnit = papszTokens[1];
     432             :             }
     433             :         }
     434         869 :         CSLDestroy(papszTokens);
     435         869 :     }
     436           2 :     VSIFCloseL(fpStructure);
     437             : }
     438             : 
     439             : /************************************************************************/
     440             : /*                            ResetReading()                            */
     441             : /************************************************************************/
     442             : 
     443           2 : void OGRPDSLayer::ResetReading()
     444             : 
     445             : {
     446           2 :     nNextFID = 0;
     447           2 :     VSIFSeekL(fpPDS, nStartBytes, SEEK_SET);
     448           2 : }
     449             : 
     450             : /************************************************************************/
     451             : /*                         GetNextRawFeature()                          */
     452             : /************************************************************************/
     453             : 
     454           3 : OGRFeature *OGRPDSLayer::GetNextRawFeature()
     455             : {
     456           3 :     if (nNextFID == nRecords)
     457           0 :         return nullptr;
     458           3 :     int nRead = (int)VSIFReadL(pabyRecord, 1, nRecordSize, fpPDS);
     459           3 :     if (nRead != nRecordSize)
     460           0 :         return nullptr;
     461             : 
     462           3 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     463           3 :     int nFieldCount = poFeatureDefn->GetFieldCount();
     464           3 :     if (pasFieldDesc != nullptr)
     465             :     {
     466          86 :         for (int i = 0; i < nFieldCount; i++)
     467             :         {
     468          83 :             if (pasFieldDesc[i].eFormat == ASCII_REAL ||
     469          55 :                 pasFieldDesc[i].eFormat == ASCII_INTEGER ||
     470          33 :                 pasFieldDesc[i].eFormat == CHARACTER)
     471             :             {
     472          52 :                 char *pchEnd = reinterpret_cast<char *>(
     473          52 :                     &pabyRecord[pasFieldDesc[i].nStartByte +
     474          52 :                                 pasFieldDesc[i].nByteCount]);
     475          52 :                 char chSaved = *pchEnd;
     476          52 :                 *pchEnd = 0;
     477          52 :                 const char *pszValue =
     478          52 :                     (const char *)(pabyRecord + pasFieldDesc[i].nStartByte);
     479          52 :                 if (pasFieldDesc[i].eFormat == CHARACTER)
     480             :                 {
     481           2 :                     poFeature->SetField(i, pszValue);
     482             :                 }
     483             :                 else
     484             :                 {
     485          50 :                     poFeature->SetField(i, CPLString(pszValue).Trim().c_str());
     486             :                 }
     487          52 :                 *pchEnd = chSaved;
     488             :             }
     489          31 :             else if (pasFieldDesc[i].eFormat == MSB_UNSIGNED_INTEGER &&
     490          11 :                      pasFieldDesc[i].nStartByte + pasFieldDesc[i].nItemBytes *
     491          11 :                                                       pasFieldDesc[i].nItems <=
     492          11 :                          nRecordSize)
     493             :             {
     494          11 :                 if (pasFieldDesc[i].nItemBytes == 1)
     495             :                 {
     496           0 :                     if (pasFieldDesc[i].nItems > 1)
     497             :                     {
     498             :                         int *panValues = static_cast<int *>(
     499           0 :                             CPLMalloc(sizeof(int) * pasFieldDesc[i].nItems));
     500           0 :                         for (int j = 0; j < pasFieldDesc[i].nItems; j++)
     501             :                         {
     502           0 :                             panValues[j] =
     503           0 :                                 pabyRecord[pasFieldDesc[i].nStartByte + j];
     504             :                         }
     505           0 :                         poFeature->SetField(i, pasFieldDesc[i].nItems,
     506             :                                             panValues);
     507           0 :                         CPLFree(panValues);
     508             :                     }
     509             :                     else
     510             :                     {
     511           0 :                         poFeature->SetField(
     512           0 :                             i, pabyRecord[pasFieldDesc[i].nStartByte]);
     513             :                     }
     514             :                 }
     515          11 :                 else if (pasFieldDesc[i].nItemBytes == 2)
     516             :                 {
     517           9 :                     if (pasFieldDesc[i].nItems > 1)
     518             :                     {
     519           0 :                         int *panValues = (int *)CPLMalloc(
     520           0 :                             sizeof(int) * pasFieldDesc[i].nItems);
     521           0 :                         for (int j = 0; j < pasFieldDesc[i].nItems; j++)
     522             :                         {
     523           0 :                             unsigned short sVal = 0;
     524           0 :                             memcpy(&sVal,
     525           0 :                                    pabyRecord + pasFieldDesc[i].nStartByte +
     526           0 :                                        2 * j,
     527             :                                    2);
     528           0 :                             CPL_MSBPTR16(&sVal);
     529           0 :                             panValues[j] = sVal;
     530             :                         }
     531           0 :                         poFeature->SetField(i, pasFieldDesc[i].nItems,
     532             :                                             panValues);
     533           0 :                         CPLFree(panValues);
     534             :                     }
     535             :                     else
     536             :                     {
     537           9 :                         unsigned short sVal = 0;
     538           9 :                         memcpy(&sVal, pabyRecord + pasFieldDesc[i].nStartByte,
     539             :                                2);
     540           9 :                         CPL_MSBPTR16(&sVal);
     541           9 :                         poFeature->SetField(i, (int)sVal);
     542             :                     }
     543             :                 }
     544           2 :                 else if (pasFieldDesc[i].nItemBytes == 4)
     545             :                 {
     546           2 :                     if (pasFieldDesc[i].nItems > 1)
     547             :                     {
     548           0 :                         double *padfValues = (double *)CPLMalloc(
     549           0 :                             sizeof(double) * pasFieldDesc[i].nItems);
     550           0 :                         for (int j = 0; j < pasFieldDesc[i].nItems; j++)
     551             :                         {
     552           0 :                             unsigned int nVal = 0;
     553           0 :                             memcpy(&nVal,
     554           0 :                                    pabyRecord + pasFieldDesc[i].nStartByte +
     555           0 :                                        4 * j,
     556             :                                    4);
     557           0 :                             CPL_MSBPTR32(&nVal);
     558           0 :                             padfValues[j] = (double)nVal;
     559             :                         }
     560           0 :                         poFeature->SetField(i, pasFieldDesc[i].nItems,
     561             :                                             padfValues);
     562           0 :                         CPLFree(padfValues);
     563             :                     }
     564             :                     else
     565             :                     {
     566           2 :                         unsigned int nVal = 0;
     567           2 :                         memcpy(&nVal, pabyRecord + pasFieldDesc[i].nStartByte,
     568             :                                4);
     569           2 :                         CPL_MSBPTR32(&nVal);
     570           2 :                         poFeature->SetField(i, (double)nVal);
     571             :                     }
     572          11 :                 }
     573             :             }
     574          20 :             else if (pasFieldDesc[i].eFormat == MSB_INTEGER &&
     575           4 :                      pasFieldDesc[i].nStartByte + pasFieldDesc[i].nItemBytes *
     576           4 :                                                       pasFieldDesc[i].nItems <=
     577           4 :                          nRecordSize)
     578             :             {
     579           4 :                 if (pasFieldDesc[i].nItemBytes == 1)
     580             :                 {
     581           0 :                     if (pasFieldDesc[i].nItems > 1)
     582             :                     {
     583           0 :                         int *panValues = (int *)CPLMalloc(
     584           0 :                             sizeof(int) * pasFieldDesc[i].nItems);
     585           0 :                         for (int j = 0; j < pasFieldDesc[i].nItems; j++)
     586             :                         {
     587           0 :                             panValues[j] = ((
     588           0 :                                 char *)pabyRecord)[pasFieldDesc[i].nStartByte +
     589           0 :                                                    j];
     590             :                         }
     591           0 :                         poFeature->SetField(i, pasFieldDesc[i].nItems,
     592             :                                             panValues);
     593           0 :                         CPLFree(panValues);
     594             :                     }
     595             :                     else
     596             :                     {
     597           0 :                         poFeature->SetField(
     598             :                             i,
     599           0 :                             ((char *)pabyRecord)[pasFieldDesc[i].nStartByte]);
     600             :                     }
     601             :                 }
     602           4 :                 else if (pasFieldDesc[i].nItemBytes == 2)
     603             :                 {
     604           0 :                     if (pasFieldDesc[i].nItems > 1)
     605             :                     {
     606           0 :                         int *panValues = (int *)CPLMalloc(
     607           0 :                             sizeof(int) * pasFieldDesc[i].nItems);
     608           0 :                         for (int j = 0; j < pasFieldDesc[i].nItems; j++)
     609             :                         {
     610           0 :                             short sVal = 0;
     611           0 :                             memcpy(&sVal,
     612           0 :                                    pabyRecord + pasFieldDesc[i].nStartByte +
     613           0 :                                        2 * j,
     614             :                                    2);
     615           0 :                             CPL_MSBPTR16(&sVal);
     616           0 :                             panValues[j] = sVal;
     617             :                         }
     618           0 :                         poFeature->SetField(i, pasFieldDesc[i].nItems,
     619             :                                             panValues);
     620           0 :                         CPLFree(panValues);
     621             :                     }
     622             :                     else
     623             :                     {
     624           0 :                         short sVal = 0;
     625           0 :                         memcpy(&sVal, pabyRecord + pasFieldDesc[i].nStartByte,
     626             :                                2);
     627           0 :                         CPL_MSBPTR16(&sVal);
     628           0 :                         poFeature->SetField(i, (int)sVal);
     629             :                     }
     630             :                 }
     631           4 :                 else if (pasFieldDesc[i].nItemBytes == 4)
     632             :                 {
     633           4 :                     if (pasFieldDesc[i].nItems > 1)
     634             :                     {
     635           0 :                         int *panValues = (int *)CPLMalloc(
     636           0 :                             sizeof(int) * pasFieldDesc[i].nItems);
     637           0 :                         for (int j = 0; j < pasFieldDesc[i].nItems; j++)
     638             :                         {
     639           0 :                             int nVal = 0;
     640           0 :                             memcpy(&nVal,
     641           0 :                                    pabyRecord + pasFieldDesc[i].nStartByte +
     642           0 :                                        4 * j,
     643             :                                    4);
     644           0 :                             CPL_MSBPTR32(&nVal);
     645           0 :                             panValues[j] = nVal;
     646             :                         }
     647           0 :                         poFeature->SetField(i, pasFieldDesc[i].nItems,
     648             :                                             panValues);
     649           0 :                         CPLFree(panValues);
     650             :                     }
     651             :                     else
     652             :                     {
     653           4 :                         int nVal = 0;
     654           4 :                         memcpy(&nVal, pabyRecord + pasFieldDesc[i].nStartByte,
     655             :                                4);
     656           4 :                         CPL_MSBPTR32(&nVal);
     657           4 :                         poFeature->SetField(i, nVal);
     658             :                     }
     659           4 :                 }
     660             :             }
     661          16 :             else if (pasFieldDesc[i].eFormat == IEEE_REAL &&
     662          16 :                      pasFieldDesc[i].nStartByte + pasFieldDesc[i].nItemBytes *
     663          16 :                                                       pasFieldDesc[i].nItems <=
     664          16 :                          nRecordSize &&
     665          16 :                      pasFieldDesc[i].nItemBytes == 4)
     666             :             {
     667           8 :                 if (pasFieldDesc[i].nItems > 1)
     668             :                 {
     669          10 :                     double *padfValues = (double *)CPLMalloc(
     670           5 :                         sizeof(double) * pasFieldDesc[i].nItems);
     671        2565 :                     for (int j = 0; j < pasFieldDesc[i].nItems; j++)
     672             :                     {
     673        2560 :                         float fVal = 0.0f;
     674        2560 :                         memcpy(&fVal,
     675        2560 :                                pabyRecord + pasFieldDesc[i].nStartByte + 4 * j,
     676             :                                4);
     677        2560 :                         CPL_MSBPTR32(&fVal);
     678        2560 :                         padfValues[j] = (double)fVal;
     679             :                     }
     680           5 :                     poFeature->SetField(i, pasFieldDesc[i].nItems, padfValues);
     681           5 :                     CPLFree(padfValues);
     682             :                 }
     683             :                 else
     684             :                 {
     685           3 :                     float fVal = 0.0f;
     686           3 :                     memcpy(&fVal, pabyRecord + pasFieldDesc[i].nStartByte, 4);
     687           3 :                     CPL_MSBPTR32(&fVal);
     688           3 :                     poFeature->SetField(i, (double)fVal);
     689           8 :                 }
     690             :             }
     691           8 :             else if (pasFieldDesc[i].eFormat == IEEE_REAL &&
     692           8 :                      pasFieldDesc[i].nStartByte + pasFieldDesc[i].nItemBytes *
     693           8 :                                                       pasFieldDesc[i].nItems <=
     694           8 :                          nRecordSize &&
     695           8 :                      pasFieldDesc[i].nItemBytes == 8)
     696             :             {
     697           8 :                 if (pasFieldDesc[i].nItems > 1)
     698             :                 {
     699           4 :                     double *padfValues = (double *)CPLMalloc(
     700           2 :                         sizeof(double) * pasFieldDesc[i].nItems);
     701          12 :                     for (int j = 0; j < pasFieldDesc[i].nItems; j++)
     702             :                     {
     703          10 :                         double dfVal = 0.0;
     704          10 :                         memcpy(&dfVal,
     705          10 :                                pabyRecord + pasFieldDesc[i].nStartByte + 8 * j,
     706             :                                8);
     707          10 :                         CPL_MSBPTR64(&dfVal);
     708          10 :                         padfValues[j] = dfVal;
     709             :                     }
     710           2 :                     poFeature->SetField(i, pasFieldDesc[i].nItems, padfValues);
     711           2 :                     CPLFree(padfValues);
     712             :                 }
     713             :                 else
     714             :                 {
     715           6 :                     double dfVal = 0.0;
     716           6 :                     memcpy(&dfVal, pabyRecord + pasFieldDesc[i].nStartByte, 8);
     717           6 :                     CPL_MSBPTR64(&dfVal);
     718           6 :                     poFeature->SetField(i, dfVal);
     719             :                 }
     720             :             }
     721             :         }
     722             :     }
     723             :     else
     724             :     {
     725           0 :         char **papszTokens = CSLTokenizeString2((const char *)pabyRecord, " ",
     726             :                                                 CSLT_HONOURSTRINGS);
     727           0 :         const int nTokens = std::min(CSLCount(papszTokens), nFieldCount);
     728           0 :         for (int i = 0; i < nTokens; i++)
     729             :         {
     730           0 :             poFeature->SetField(i, papszTokens[i]);
     731             :         }
     732           0 :         CSLDestroy(papszTokens);
     733             :     }
     734             : 
     735           3 :     if (nLongitudeIndex >= 0 && nLatitudeIndex >= 0)
     736           2 :         poFeature->SetGeometryDirectly(
     737           2 :             new OGRPoint(poFeature->GetFieldAsDouble(nLongitudeIndex),
     738           2 :                          poFeature->GetFieldAsDouble(nLatitudeIndex)));
     739             : 
     740           3 :     poFeature->SetFID(nNextFID++);
     741             : 
     742           3 :     return poFeature;
     743             : }
     744             : 
     745             : /************************************************************************/
     746             : /*                           TestCapability()                           */
     747             : /************************************************************************/
     748             : 
     749           1 : int OGRPDSLayer::TestCapability(const char *pszCap)
     750             : 
     751             : {
     752           1 :     if (EQUAL(pszCap, OLCFastFeatureCount) && m_poFilterGeom == nullptr &&
     753           1 :         m_poAttrQuery == nullptr)
     754           1 :         return TRUE;
     755             : 
     756           0 :     if (EQUAL(pszCap, OLCRandomRead))
     757           0 :         return TRUE;
     758             : 
     759           0 :     if (EQUAL(pszCap, OLCFastSetNextByIndex) && m_poFilterGeom == nullptr &&
     760           0 :         m_poAttrQuery == nullptr)
     761           0 :         return TRUE;
     762             : 
     763           0 :     return FALSE;
     764             : }
     765             : 
     766             : /************************************************************************/
     767             : /*                          GetFeatureCount()                           */
     768             : /************************************************************************/
     769             : 
     770           1 : GIntBig OGRPDSLayer::GetFeatureCount(int bForce)
     771             : {
     772           1 :     if (TestCapability(OLCFastFeatureCount))
     773           1 :         return nRecords;
     774             : 
     775           0 :     return OGRLayer::GetFeatureCount(bForce);
     776             : }
     777             : 
     778             : /************************************************************************/
     779             : /*                             GetFeature()                             */
     780             : /************************************************************************/
     781             : 
     782           1 : OGRFeature *OGRPDSLayer::GetFeature(GIntBig nFID)
     783             : {
     784           1 :     if (nFID < 0 || nFID >= nRecords)
     785           0 :         return nullptr;
     786             : 
     787           1 :     nNextFID = (int)nFID;
     788           1 :     VSIFSeekL(fpPDS, nStartBytes + nNextFID * nRecordSize, SEEK_SET);
     789           1 :     return GetNextRawFeature();
     790             : }
     791             : 
     792             : /************************************************************************/
     793             : /*                         SetNextByIndex()                             */
     794             : /************************************************************************/
     795             : 
     796           0 : OGRErr OGRPDSLayer::SetNextByIndex(GIntBig nIndex)
     797             : {
     798           0 :     if (!TestCapability(OLCFastSetNextByIndex))
     799           0 :         return OGRLayer::SetNextByIndex(nIndex);
     800             : 
     801           0 :     if (nIndex < 0 || nIndex >= nRecords)
     802           0 :         return OGRERR_FAILURE;
     803             : 
     804           0 :     nNextFID = (int)nIndex;
     805           0 :     VSIFSeekL(fpPDS, nStartBytes + nNextFID * nRecordSize, SEEK_SET);
     806           0 :     return OGRERR_NONE;
     807             : }
     808             : 
     809             : }  // namespace OGRPDS

Generated by: LCOV version 1.14