LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/ntf - ntfrecord.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 85 0.0 %
Date: 2024-11-25 13:07:18 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  NTF Translator
       4             :  * Purpose:  NTFRecord class implementation.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999, Frank Warmerdam
       9             :  * Copyright (c) 2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "ntf.h"
      15             : #include "cpl_conv.h"
      16             : 
      17             : static int nFieldBufSize = 0;
      18             : static char *pszFieldBuf = nullptr;
      19             : 
      20             : constexpr int MAX_RECORD_LEN = 160;
      21             : 
      22             : /************************************************************************/
      23             : /*                             NTFRecord()                              */
      24             : /*                                                                      */
      25             : /*      The constructor is where the record is read.  This includes     */
      26             : /*      transparent merging of continuation lines.                      */
      27             : /************************************************************************/
      28             : 
      29           0 : NTFRecord::NTFRecord(VSILFILE *fp) : nType(99), nLength(0), pszData(nullptr)
      30             : {
      31           0 :     if (fp == nullptr)
      32           0 :         return;
      33             : 
      34             :     /* ==================================================================== */
      35             :     /*      Read lines until we get to one without a continuation mark.     */
      36             :     /* ==================================================================== */
      37           0 :     char szLine[MAX_RECORD_LEN + 3] = {};
      38           0 :     int nNewLength = 0;
      39             : 
      40           0 :     do
      41             :     {
      42           0 :         nNewLength = ReadPhysicalLine(fp, szLine);
      43           0 :         if (nNewLength == -1 || nNewLength == -2)
      44             :             break;
      45             : 
      46           0 :         while (nNewLength > 0 && szLine[nNewLength - 1] == ' ')
      47           0 :             szLine[--nNewLength] = '\0';
      48             : 
      49           0 :         if (nNewLength < 2 || szLine[nNewLength - 1] != '%')
      50             :         {
      51           0 :             CPLError(CE_Failure, CPLE_AppDefined,
      52             :                      "Corrupt NTF record, missing end '%%'.");
      53           0 :             CPLFree(pszData);
      54           0 :             pszData = nullptr;
      55           0 :             break;
      56             :         }
      57             : 
      58           0 :         if (pszData == nullptr)
      59             :         {
      60           0 :             nLength = nNewLength - 2;
      61             :             // coverity[overflow_sink]
      62           0 :             pszData = static_cast<char *>(VSI_MALLOC_VERBOSE(nLength + 1));
      63           0 :             if (pszData == nullptr)
      64             :             {
      65           0 :                 return;
      66             :             }
      67           0 :             memcpy(pszData, szLine, nLength);
      68           0 :             pszData[nLength] = '\0';
      69             :         }
      70             :         else
      71             :         {
      72           0 :             if (!STARTS_WITH_CI(szLine, "00") || nNewLength < 4)
      73             :             {
      74           0 :                 CPLError(CE_Failure, CPLE_AppDefined, "Invalid line");
      75           0 :                 VSIFree(pszData);
      76           0 :                 pszData = nullptr;
      77           0 :                 return;
      78             :             }
      79             : 
      80             :             char *pszNewData = static_cast<char *>(
      81           0 :                 VSI_REALLOC_VERBOSE(pszData, nLength + (nNewLength - 4) + 1));
      82           0 :             if (pszNewData == nullptr)
      83             :             {
      84           0 :                 VSIFree(pszData);
      85           0 :                 pszData = nullptr;
      86           0 :                 return;
      87             :             }
      88             : 
      89           0 :             pszData = pszNewData;
      90           0 :             memcpy(pszData + nLength, szLine + 2, nNewLength - 4);
      91           0 :             nLength += nNewLength - 4;
      92           0 :             pszData[nLength] = '\0';
      93             :         }
      94           0 :     } while (szLine[nNewLength - 2] == '1');
      95             : 
      96             :     /* -------------------------------------------------------------------- */
      97             :     /*      Figure out the record type.                                     */
      98             :     /* -------------------------------------------------------------------- */
      99           0 :     if (pszData != nullptr)
     100             :     {
     101             :         char szType[3];
     102             : 
     103           0 :         strncpy(szType, pszData, 2);
     104           0 :         szType[2] = '\0';
     105             : 
     106           0 :         nType = atoi(szType);
     107             :     }
     108             : }
     109             : 
     110             : /************************************************************************/
     111             : /*                             ~NTFRecord()                             */
     112             : /************************************************************************/
     113             : 
     114           0 : NTFRecord::~NTFRecord()
     115             : 
     116             : {
     117           0 :     CPLFree(pszData);
     118             : 
     119           0 :     if (pszFieldBuf != nullptr)
     120             :     {
     121           0 :         CPLFree(pszFieldBuf);
     122           0 :         pszFieldBuf = nullptr;
     123           0 :         nFieldBufSize = 0;
     124             :     }
     125           0 : }
     126             : 
     127             : /************************************************************************/
     128             : /*                          ReadPhysicalLine()                          */
     129             : /************************************************************************/
     130             : 
     131           0 : int NTFRecord::ReadPhysicalLine(VSILFILE *fp, char *pszLine)
     132             : 
     133             : {
     134             :     /* -------------------------------------------------------------------- */
     135             :     /*      Read enough data that we are sure we have a whole record.       */
     136             :     /* -------------------------------------------------------------------- */
     137           0 :     int nRecordStart = static_cast<int>(VSIFTellL(fp));
     138             :     const int nBytesRead =
     139           0 :         static_cast<int>(VSIFReadL(pszLine, 1, MAX_RECORD_LEN + 2, fp));
     140             : 
     141           0 :     if (nBytesRead == 0)
     142             :     {
     143           0 :         if (VSIFEofL(fp))
     144           0 :             return -1;
     145             :         else /* if (VSIFErrorL(fp)) */
     146             :         {
     147           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     148             :                      "Low level read error occurred while reading NTF file.");
     149           0 :             return -2;
     150             :         }
     151             :     }
     152             : 
     153             :     /* -------------------------------------------------------------------- */
     154             :     /*      Search for CR or LF.                                            */
     155             :     /* -------------------------------------------------------------------- */
     156           0 :     int i = 0;  // Used after for.
     157           0 :     for (; i < nBytesRead; i++)
     158             :     {
     159           0 :         if (pszLine[i] == 10 || pszLine[i] == 13)
     160             :             break;
     161             :     }
     162             : 
     163             :     /* -------------------------------------------------------------------- */
     164             :     /*      If we don't find EOL within 80 characters something has gone    */
     165             :     /*      badly wrong!                                                    */
     166             :     /* -------------------------------------------------------------------- */
     167           0 :     if (i == MAX_RECORD_LEN + 2)
     168             :     {
     169           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     170             :                  "%d byte record too long for NTF format.  "
     171             :                  "No line may be longer than 80 characters though up "
     172             :                  "to %d tolerated.",
     173             :                  nBytesRead, MAX_RECORD_LEN);
     174           0 :         return -2;
     175             :     }
     176             : 
     177             :     /* -------------------------------------------------------------------- */
     178             :     /*      Trim CR/LF.                                                     */
     179             :     /* -------------------------------------------------------------------- */
     180           0 :     const int l_nLength = i;
     181           0 :     const int nRecordEnd =
     182           0 :         nRecordStart + i +
     183           0 :         (pszLine[i + 1] == 10 || pszLine[i + 1] == 13 ? 2 : 1);
     184             : 
     185           0 :     pszLine[l_nLength] = '\0';
     186             : 
     187             :     /* -------------------------------------------------------------------- */
     188             :     /*      Restore read pointer to beginning of next record.               */
     189             :     /* -------------------------------------------------------------------- */
     190           0 :     if (VSIFSeekL(fp, nRecordEnd, SEEK_SET) != 0)
     191           0 :         return -1;
     192             : 
     193           0 :     return l_nLength;
     194             : }
     195             : 
     196             : /************************************************************************/
     197             : /*                              GetField()                              */
     198             : /*                                                                      */
     199             : /*      Note that the start position is 1 based, to match the           */
     200             : /*      notation in the NTF document.  The returned pointer is to an    */
     201             : /*      internal buffer, but is zero terminated.                        */
     202             : /************************************************************************/
     203             : 
     204           0 : const char *NTFRecord::GetField(int nStart, int nEnd)
     205             : 
     206             : {
     207           0 :     const int nSize = nEnd - nStart + 1;
     208             : 
     209           0 :     if (pszData == nullptr)
     210           0 :         return "";
     211             : 
     212             :     /* -------------------------------------------------------------------- */
     213             :     /*      Reallocate working buffer larger if needed.                     */
     214             :     /* -------------------------------------------------------------------- */
     215           0 :     if (nFieldBufSize < nSize + 1)
     216             :     {
     217           0 :         CPLFree(pszFieldBuf);
     218           0 :         nFieldBufSize = nSize + 1;
     219           0 :         pszFieldBuf = static_cast<char *>(CPLMalloc(nFieldBufSize));
     220             :     }
     221             : 
     222             :     /* -------------------------------------------------------------------- */
     223             :     /*      Copy out desired data.                                          */
     224             :     /* -------------------------------------------------------------------- */
     225           0 :     if (nStart + nSize > nLength + 1)
     226             :     {
     227           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     228             :                  "Attempt to read %d to %d, beyond the end of %d byte long\n"
     229             :                  "type `%2.2s' record.\n",
     230             :                  nStart, nEnd, nLength, pszData);
     231           0 :         memset(pszFieldBuf, ' ', nSize);
     232           0 :         pszFieldBuf[nSize] = '\0';
     233             :     }
     234             :     else
     235             :     {
     236           0 :         strncpy(pszFieldBuf, pszData + nStart - 1, nSize);
     237           0 :         pszFieldBuf[nSize] = '\0';
     238             :     }
     239             : 
     240           0 :     return pszFieldBuf;
     241             : }

Generated by: LCOV version 1.14