1 : /******************************************************************************
2 : * $Id: ntfrecord.cpp 25504 2013-01-14 22:18:55Z rouault $
3 : *
4 : * Project: NTF Translator
5 : * Purpose: NTFRecord class implementation.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ntf.h"
31 : #include "cpl_conv.h"
32 :
33 : CPL_CVSID("$Id: ntfrecord.cpp 25504 2013-01-14 22:18:55Z rouault $");
34 :
35 : static int nFieldBufSize = 0;
36 : static char *pszFieldBuf = NULL;
37 :
38 : #define MAX_RECORD_LEN 160
39 :
40 : /************************************************************************/
41 : /* NTFRecord() */
42 : /* */
43 : /* The constructor is where the record is read. This includes */
44 : /* transparent merging of continuation lines. */
45 : /************************************************************************/
46 :
47 322954 : NTFRecord::NTFRecord( FILE * fp )
48 :
49 : {
50 322954 : nType = 99;
51 322954 : nLength = 0;
52 322954 : pszData = NULL;
53 :
54 322954 : if( fp == NULL )
55 0 : return;
56 :
57 : /* ==================================================================== */
58 : /* Read lines untill we get to one without a continuation mark. */
59 : /* ==================================================================== */
60 : char szLine[MAX_RECORD_LEN+3];
61 : int nNewLength;
62 :
63 804686 : do {
64 402343 : nNewLength = ReadPhysicalLine( fp, szLine );
65 402343 : if( nNewLength == -1 || nNewLength == -2 )
66 0 : break;
67 :
68 804686 : while( nNewLength > 0 && szLine[nNewLength-1] == ' ' )
69 0 : szLine[--nNewLength] = '\0';
70 :
71 402343 : if( szLine[nNewLength-1] != '%' )
72 : {
73 : CPLError( CE_Failure, CPLE_AppDefined,
74 0 : "Corrupt NTF record, missing end '%%'." );
75 0 : CPLFree( pszData );
76 0 : pszData = NULL;
77 0 : break;
78 : }
79 :
80 402343 : if( pszData == NULL )
81 : {
82 322954 : nLength = nNewLength - 2;
83 322954 : pszData = (char *) VSIMalloc(nLength+1);
84 322954 : if (pszData == NULL)
85 : {
86 0 : CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
87 0 : return;
88 : }
89 322954 : memcpy( pszData, szLine, nLength );
90 322954 : pszData[nLength] = '\0';
91 : }
92 : else
93 : {
94 79389 : if( !EQUALN(szLine,"00",2) )
95 : {
96 0 : CPLError( CE_Failure, CPLE_AppDefined, "Invalid line");
97 0 : VSIFree(pszData);
98 0 : pszData = NULL;
99 0 : return;
100 : }
101 :
102 79389 : char* pszNewData = (char *) VSIRealloc(pszData,nLength+(nNewLength-4)+1);
103 79389 : if (pszNewData == NULL)
104 : {
105 0 : CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
106 0 : VSIFree(pszData);
107 0 : pszData = NULL;
108 0 : return;
109 : }
110 :
111 79389 : pszData = pszNewData;
112 79389 : memcpy( pszData+nLength, szLine+2, nNewLength-4 );
113 79389 : nLength += nNewLength-4;
114 79389 : pszData[nLength] = '\0';
115 : }
116 402343 : } while( szLine[nNewLength-2] == '1' );
117 :
118 : /* -------------------------------------------------------------------- */
119 : /* Figure out the record type. */
120 : /* -------------------------------------------------------------------- */
121 322954 : if( pszData != NULL )
122 : {
123 : char szType[3];
124 :
125 322954 : strncpy( szType, pszData, 2 );
126 322954 : szType[2] = '\0';
127 :
128 322954 : nType = atoi(szType);
129 : }
130 : }
131 :
132 : /************************************************************************/
133 : /* ~NTFRecord() */
134 : /************************************************************************/
135 :
136 322954 : NTFRecord::~NTFRecord()
137 :
138 : {
139 322954 : CPLFree( pszData );
140 :
141 322954 : if( pszFieldBuf != NULL )
142 : {
143 31548 : CPLFree( pszFieldBuf );
144 31548 : pszFieldBuf = NULL;
145 31548 : nFieldBufSize = 0;
146 : }
147 322954 : }
148 :
149 : /************************************************************************/
150 : /* ReadPhysicalLine() */
151 : /************************************************************************/
152 :
153 402343 : int NTFRecord::ReadPhysicalLine( FILE *fp, char *pszLine )
154 :
155 : {
156 402343 : int nBytesRead = 0;
157 402343 : int nRecordStart, nRecordEnd, i, nLength = 0;
158 :
159 : /* -------------------------------------------------------------------- */
160 : /* Read enough data that we are sure we have a whole record. */
161 : /* -------------------------------------------------------------------- */
162 402343 : nRecordStart = VSIFTell( fp );
163 402343 : nBytesRead = VSIFRead( pszLine, 1, MAX_RECORD_LEN+2, fp );
164 :
165 402343 : if( nBytesRead == 0 )
166 : {
167 0 : if( VSIFEof( fp ) )
168 0 : return -1;
169 : else
170 : {
171 : CPLError( CE_Failure, CPLE_AppDefined,
172 0 : "Low level read error occured while reading NTF file." );
173 0 : return -2;
174 : }
175 : }
176 :
177 : /* -------------------------------------------------------------------- */
178 : /* Search for CR or LF. */
179 : /* -------------------------------------------------------------------- */
180 17353309 : for( i = 0; i < nBytesRead; i++ )
181 : {
182 17353309 : if( pszLine[i] == 10 || pszLine[i] == 13 )
183 402343 : break;
184 : }
185 :
186 : /* -------------------------------------------------------------------- */
187 : /* If we don't find EOL within 80 characters something has gone */
188 : /* badly wrong! */
189 : /* -------------------------------------------------------------------- */
190 402343 : if( i == MAX_RECORD_LEN+2 )
191 : {
192 : CPLError( CE_Failure, CPLE_AppDefined,
193 : "%d byte record too long for NTF format.\n"
194 : "No line may be longer than 80 characters though up to %d tolerated.\n",
195 0 : nBytesRead, MAX_RECORD_LEN );
196 0 : return -2;
197 : }
198 :
199 : /* -------------------------------------------------------------------- */
200 : /* Trim CR/LF. */
201 : /* -------------------------------------------------------------------- */
202 402343 : nLength = i;
203 804686 : if( pszLine[i+1] == 10 || pszLine[i+1] == 13 )
204 402343 : nRecordEnd = nRecordStart + i + 2;
205 : else
206 0 : nRecordEnd = nRecordStart + i + 1;
207 :
208 402343 : pszLine[nLength] = '\0';
209 :
210 : /* -------------------------------------------------------------------- */
211 : /* Restore read pointer to beginning of next record. */
212 : /* -------------------------------------------------------------------- */
213 402343 : VSIFSeek( fp, nRecordEnd, SEEK_SET );
214 :
215 402343 : return nLength;
216 : }
217 :
218 : /************************************************************************/
219 : /* GetField() */
220 : /* */
221 : /* Note that the start position is 1 based, to match the */
222 : /* notation in the NTF document. The returned pointer is to an */
223 : /* internal buffer, but is zero terminated. */
224 : /************************************************************************/
225 :
226 551971 : const char * NTFRecord::GetField( int nStart, int nEnd )
227 :
228 : {
229 551971 : int nSize = nEnd - nStart + 1;
230 :
231 : /* -------------------------------------------------------------------- */
232 : /* Reallocate working buffer larger if needed. */
233 : /* -------------------------------------------------------------------- */
234 551971 : if( nFieldBufSize < nSize + 1 )
235 : {
236 66108 : CPLFree( pszFieldBuf );
237 66108 : nFieldBufSize = nSize + 1;
238 66108 : pszFieldBuf = (char *) CPLMalloc(nFieldBufSize);
239 : }
240 :
241 : /* -------------------------------------------------------------------- */
242 : /* Copy out desired data. */
243 : /* -------------------------------------------------------------------- */
244 551971 : if( nStart + nSize > nLength+1 )
245 : {
246 : CPLError( CE_Failure, CPLE_AppDefined,
247 : "Attempt to read %d to %d, beyond the end of %d byte long\n"
248 : "type `%2.2s' record.\n",
249 0 : nStart, nEnd, nLength, pszData );
250 0 : memset( pszFieldBuf, ' ', nSize );
251 0 : pszFieldBuf[nSize] = '\0';
252 : }
253 : else
254 : {
255 551971 : strncpy( pszFieldBuf, pszData + nStart - 1, nSize );
256 551971 : pszFieldBuf[nSize] = '\0';
257 : }
258 :
259 551971 : return pszFieldBuf;
260 : }
261 :
262 :
263 :
|