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

Generated by: LCOV version 1.14