EVOLUTION-MANAGER
Edit File: ntfrecord.cpp
/****************************************************************************** * $Id: ntfrecord.cpp 32417 2015-12-21 10:16:22Z rouault $ * * Project: NTF Translator * Purpose: NTFRecord class implementation. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1999, Frank Warmerdam * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "ntf.h" #include "cpl_conv.h" CPL_CVSID("$Id: ntfrecord.cpp 32417 2015-12-21 10:16:22Z rouault $"); static int nFieldBufSize = 0; static char *pszFieldBuf = NULL; #define MAX_RECORD_LEN 160 /************************************************************************/ /* NTFRecord() */ /* */ /* The constructor is where the record is read. This includes */ /* transparent merging of continuation lines. */ /************************************************************************/ NTFRecord::NTFRecord( FILE * fp ) { nType = 99; nLength = 0; pszData = NULL; if( fp == NULL ) return; /* ==================================================================== */ /* Read lines untill we get to one without a continuation mark. */ /* ==================================================================== */ char szLine[MAX_RECORD_LEN+3]; int nNewLength; do { nNewLength = ReadPhysicalLine( fp, szLine ); if( nNewLength == -1 || nNewLength == -2 ) break; while( nNewLength > 0 && szLine[nNewLength-1] == ' ' ) szLine[--nNewLength] = '\0'; if( nNewLength < 2 || szLine[nNewLength-1] != '%' ) { CPLError( CE_Failure, CPLE_AppDefined, "Corrupt NTF record, missing end '%%'." ); CPLFree( pszData ); pszData = NULL; break; } if( pszData == NULL ) { nLength = nNewLength - 2; pszData = (char *) VSIMalloc(nLength+1); if (pszData == NULL) { CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory"); return; } memcpy( pszData, szLine, nLength ); pszData[nLength] = '\0'; } else { if( !EQUALN(szLine,"00",2) || nNewLength < 4 ) { CPLError( CE_Failure, CPLE_AppDefined, "Invalid line"); VSIFree(pszData); pszData = NULL; return; } char* pszNewData = (char *) VSIRealloc(pszData,nLength+(nNewLength-4)+1); if (pszNewData == NULL) { CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory"); VSIFree(pszData); pszData = NULL; return; } pszData = pszNewData; memcpy( pszData+nLength, szLine+2, nNewLength-4 ); nLength += nNewLength-4; pszData[nLength] = '\0'; } } while( szLine[nNewLength-2] == '1' ); /* -------------------------------------------------------------------- */ /* Figure out the record type. */ /* -------------------------------------------------------------------- */ if( pszData != NULL ) { char szType[3]; strncpy( szType, pszData, 2 ); szType[2] = '\0'; nType = atoi(szType); } } /************************************************************************/ /* ~NTFRecord() */ /************************************************************************/ NTFRecord::~NTFRecord() { CPLFree( pszData ); if( pszFieldBuf != NULL ) { CPLFree( pszFieldBuf ); pszFieldBuf = NULL; nFieldBufSize = 0; } } /************************************************************************/ /* ReadPhysicalLine() */ /************************************************************************/ int NTFRecord::ReadPhysicalLine( FILE *fp, char *pszLine ) { int nBytesRead = 0; int nRecordStart, nRecordEnd, i, nLength = 0; /* -------------------------------------------------------------------- */ /* Read enough data that we are sure we have a whole record. */ /* -------------------------------------------------------------------- */ nRecordStart = VSIFTell( fp ); nBytesRead = VSIFRead( pszLine, 1, MAX_RECORD_LEN+2, fp ); if( nBytesRead == 0 ) { if( VSIFEof( fp ) ) return -1; else { CPLError( CE_Failure, CPLE_AppDefined, "Low level read error occured while reading NTF file." ); return -2; } } /* -------------------------------------------------------------------- */ /* Search for CR or LF. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nBytesRead; i++ ) { if( pszLine[i] == 10 || pszLine[i] == 13 ) break; } /* -------------------------------------------------------------------- */ /* If we don't find EOL within 80 characters something has gone */ /* badly wrong! */ /* -------------------------------------------------------------------- */ if( i == MAX_RECORD_LEN+2 ) { CPLError( CE_Failure, CPLE_AppDefined, "%d byte record too long for NTF format.\n" "No line may be longer than 80 characters though up to %d tolerated.\n", nBytesRead, MAX_RECORD_LEN ); return -2; } /* -------------------------------------------------------------------- */ /* Trim CR/LF. */ /* -------------------------------------------------------------------- */ nLength = i; if( pszLine[i+1] == 10 || pszLine[i+1] == 13 ) nRecordEnd = nRecordStart + i + 2; else nRecordEnd = nRecordStart + i + 1; pszLine[nLength] = '\0'; /* -------------------------------------------------------------------- */ /* Restore read pointer to beginning of next record. */ /* -------------------------------------------------------------------- */ VSIFSeek( fp, nRecordEnd, SEEK_SET ); return nLength; } /************************************************************************/ /* GetField() */ /* */ /* Note that the start position is 1 based, to match the */ /* notation in the NTF document. The returned pointer is to an */ /* internal buffer, but is zero terminated. */ /************************************************************************/ const char * NTFRecord::GetField( int nStart, int nEnd ) { int nSize = nEnd - nStart + 1; /* -------------------------------------------------------------------- */ /* Reallocate working buffer larger if needed. */ /* -------------------------------------------------------------------- */ if( nFieldBufSize < nSize + 1 ) { CPLFree( pszFieldBuf ); nFieldBufSize = nSize + 1; pszFieldBuf = (char *) CPLMalloc(nFieldBufSize); } /* -------------------------------------------------------------------- */ /* Copy out desired data. */ /* -------------------------------------------------------------------- */ if( nStart + nSize > nLength+1 ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to read %d to %d, beyond the end of %d byte long\n" "type `%2.2s' record.\n", nStart, nEnd, nLength, pszData ); memset( pszFieldBuf, ' ', nSize ); pszFieldBuf[nSize] = '\0'; } else { strncpy( pszFieldBuf, pszData + nStart - 1, nSize ); pszFieldBuf[nSize] = '\0'; } return pszFieldBuf; }