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) 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 : const char *pszLine; 38 0 : while ((pszLine = CPLReadLine2L(fp, MAX_RECORD_LEN + 2, nullptr)) != 39 : nullptr) 40 : { 41 0 : int nNewLength = static_cast<int>(strlen(pszLine)); 42 0 : while (nNewLength > 0 && pszLine[nNewLength - 1] == ' ') 43 0 : --nNewLength; 44 : 45 0 : if (nNewLength < 2 || pszLine[nNewLength - 1] != '%') 46 : { 47 0 : CPLError(CE_Failure, CPLE_AppDefined, 48 : "Corrupt NTF record, missing end '%%'."); 49 0 : osData.clear(); 50 0 : break; 51 : } 52 : 53 0 : if (osData.empty()) 54 : { 55 0 : osData.assign(pszLine, nNewLength - 2); 56 : } 57 : else 58 : { 59 0 : if (!STARTS_WITH_CI(pszLine, "00") || nNewLength < 4) 60 : { 61 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid line"); 62 0 : osData.clear(); 63 0 : return; 64 : } 65 : 66 : try 67 : { 68 0 : osData.append(pszLine + 2, nNewLength - 4); 69 : } 70 0 : catch (const std::exception &) 71 : { 72 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Too large file"); 73 0 : osData.clear(); 74 0 : return; 75 : } 76 : } 77 : 78 0 : if (pszLine[nNewLength - 2] != '1') 79 0 : break; 80 : } 81 : 82 : /* -------------------------------------------------------------------- */ 83 : /* Figure out the record type. */ 84 : /* -------------------------------------------------------------------- */ 85 0 : if (osData.size() >= 2) 86 : { 87 0 : char szType[3] = {osData[0], osData[1], 0}; 88 0 : nType = atoi(szType); 89 : } 90 : } 91 : 92 : /************************************************************************/ 93 : /* ~NTFRecord() */ 94 : /************************************************************************/ 95 : 96 0 : NTFRecord::~NTFRecord() 97 : 98 : { 99 0 : if (pszFieldBuf != nullptr) 100 : { 101 0 : CPLFree(pszFieldBuf); 102 0 : pszFieldBuf = nullptr; 103 0 : nFieldBufSize = 0; 104 : } 105 0 : } 106 : 107 : /************************************************************************/ 108 : /* GetField() */ 109 : /* */ 110 : /* Note that the start position is 1 based, to match the */ 111 : /* notation in the NTF document. The returned pointer is to an */ 112 : /* internal buffer, but is zero terminated. */ 113 : /************************************************************************/ 114 : 115 0 : const char *NTFRecord::GetField(int nStart, int nEnd) const 116 : 117 : { 118 0 : const int nSize = nEnd - nStart + 1; 119 : 120 0 : if (osData.empty()) 121 0 : return ""; 122 : 123 : /* -------------------------------------------------------------------- */ 124 : /* Reallocate working buffer larger if needed. */ 125 : /* -------------------------------------------------------------------- */ 126 0 : if (nFieldBufSize < nSize + 1) 127 : { 128 0 : CPLFree(pszFieldBuf); 129 0 : nFieldBufSize = nSize + 1; 130 0 : pszFieldBuf = static_cast<char *>(CPLMalloc(nFieldBufSize)); 131 : } 132 : 133 : /* -------------------------------------------------------------------- */ 134 : /* Copy out desired data. */ 135 : /* -------------------------------------------------------------------- */ 136 0 : if (nStart + nSize > GetLength() + 1) 137 : { 138 0 : CPLError(CE_Failure, CPLE_AppDefined, 139 : "Attempt to read %d to %d, beyond the end of %d byte long\n" 140 : "type `%2.2s' record.\n", 141 : nStart, nEnd, GetLength(), osData.c_str()); 142 0 : memset(pszFieldBuf, ' ', nSize); 143 0 : pszFieldBuf[nSize] = '\0'; 144 : } 145 : else 146 : { 147 0 : strncpy(pszFieldBuf, osData.c_str() + nStart - 1, nSize); 148 0 : pszFieldBuf[nSize] = '\0'; 149 : } 150 : 151 0 : return pszFieldBuf; 152 : }