1 : /******************************************************************************
2 : * $Id: ntfrecord.cpp 10645 2007-01-18 02:22:39Z warmerdam $
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 10645 2007-01-18 02:22:39Z warmerdam $");
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 *) CPLMalloc(nLength+1);
84 322954 : memcpy( pszData, szLine, nLength );
85 322954 : pszData[nLength] = '\0';
86 : }
87 : else
88 : {
89 79389 : pszData = (char *) CPLRealloc(pszData,nLength+(nNewLength-4)+1);
90 :
91 79389 : CPLAssert( EQUALN(szLine,"00",2) );
92 79389 : memcpy( pszData+nLength, szLine+2, nNewLength-4 );
93 79389 : nLength += nNewLength-4;
94 79389 : pszData[nLength] = '\0';
95 : }
96 402343 : } while( szLine[nNewLength-2] == '1' );
97 :
98 : /* -------------------------------------------------------------------- */
99 : /* Figure out the record type. */
100 : /* -------------------------------------------------------------------- */
101 322954 : if( pszData != NULL )
102 : {
103 : char szType[3];
104 :
105 322954 : strncpy( szType, pszData, 2 );
106 322954 : szType[2] = '\0';
107 :
108 322954 : nType = atoi(szType);
109 : }
110 : }
111 :
112 : /************************************************************************/
113 : /* ~NTFRecord() */
114 : /************************************************************************/
115 :
116 322954 : NTFRecord::~NTFRecord()
117 :
118 : {
119 322954 : CPLFree( pszData );
120 :
121 322954 : if( pszFieldBuf != NULL )
122 : {
123 31548 : CPLFree( pszFieldBuf );
124 31548 : pszFieldBuf = NULL;
125 31548 : nFieldBufSize = 0;
126 : }
127 322954 : }
128 :
129 : /************************************************************************/
130 : /* ReadPhysicalLine() */
131 : /************************************************************************/
132 :
133 402343 : int NTFRecord::ReadPhysicalLine( FILE *fp, char *pszLine )
134 :
135 : {
136 402343 : int nBytesRead = 0;
137 402343 : int nRecordStart, nRecordEnd, i, nLength = 0;
138 :
139 : /* -------------------------------------------------------------------- */
140 : /* Read enough data that we are sure we have a whole record. */
141 : /* -------------------------------------------------------------------- */
142 402343 : nRecordStart = VSIFTell( fp );
143 402343 : nBytesRead = VSIFRead( pszLine, 1, MAX_RECORD_LEN+2, fp );
144 :
145 402343 : if( nBytesRead == 0 )
146 : {
147 0 : if( VSIFEof( fp ) )
148 0 : return -1;
149 : else
150 : {
151 : CPLError( CE_Failure, CPLE_AppDefined,
152 0 : "Low level read error occured while reading NTF file." );
153 0 : return -2;
154 : }
155 : }
156 :
157 : /* -------------------------------------------------------------------- */
158 : /* Search for CR or LF. */
159 : /* -------------------------------------------------------------------- */
160 17353309 : for( i = 0; i < nBytesRead; i++ )
161 : {
162 17353309 : if( pszLine[i] == 10 || pszLine[i] == 13 )
163 402343 : break;
164 : }
165 :
166 : /* -------------------------------------------------------------------- */
167 : /* If we don't find EOL within 80 characters something has gone */
168 : /* badly wrong! */
169 : /* -------------------------------------------------------------------- */
170 402343 : if( i == MAX_RECORD_LEN+2 )
171 : {
172 : CPLError( CE_Failure, CPLE_AppDefined,
173 : "%d byte record too long for NTF format.\n"
174 : "No line may be longer than 80 characters though up to %d tolerated.\n",
175 0 : nBytesRead, MAX_RECORD_LEN );
176 0 : return -2;
177 : }
178 :
179 : /* -------------------------------------------------------------------- */
180 : /* Trim CR/LF. */
181 : /* -------------------------------------------------------------------- */
182 402343 : nLength = i;
183 804686 : if( pszLine[i+1] == 10 || pszLine[i+1] == 13 )
184 402343 : nRecordEnd = nRecordStart + i + 2;
185 : else
186 0 : nRecordEnd = nRecordStart + i + 1;
187 :
188 402343 : pszLine[nLength] = '\0';
189 :
190 : /* -------------------------------------------------------------------- */
191 : /* Restore read pointer to beginning of next record. */
192 : /* -------------------------------------------------------------------- */
193 402343 : VSIFSeek( fp, nRecordEnd, SEEK_SET );
194 :
195 402343 : return nLength;
196 : }
197 :
198 : /************************************************************************/
199 : /* GetField() */
200 : /* */
201 : /* Note that the start position is 1 based, to match the */
202 : /* notation in the NTF document. The returned pointer is to an */
203 : /* internal buffer, but is zero terminated. */
204 : /************************************************************************/
205 :
206 551971 : const char * NTFRecord::GetField( int nStart, int nEnd )
207 :
208 : {
209 551971 : int nSize = nEnd - nStart + 1;
210 :
211 : /* -------------------------------------------------------------------- */
212 : /* Reallocate working buffer larger if needed. */
213 : /* -------------------------------------------------------------------- */
214 551971 : if( nFieldBufSize < nSize + 1 )
215 : {
216 66108 : CPLFree( pszFieldBuf );
217 66108 : nFieldBufSize = nSize + 1;
218 66108 : pszFieldBuf = (char *) CPLMalloc(nFieldBufSize);
219 : }
220 :
221 : /* -------------------------------------------------------------------- */
222 : /* Copy out desired data. */
223 : /* -------------------------------------------------------------------- */
224 551971 : if( nStart + nSize > nLength+1 )
225 : {
226 : CPLError( CE_Failure, CPLE_AppDefined,
227 : "Attempt to read %d to %d, beyond the end of %d byte long\n"
228 : "type `%2.2s' record.\n",
229 0 : nStart, nEnd, nLength, pszData );
230 0 : memset( pszFieldBuf, ' ', nSize );
231 0 : pszFieldBuf[nSize] = '\0';
232 : }
233 : else
234 : {
235 551971 : strncpy( pszFieldBuf, pszData + nStart - 1, nSize );
236 551971 : pszFieldBuf[nSize] = '\0';
237 : }
238 :
239 551971 : return pszFieldBuf;
240 : }
241 :
242 :
243 :
|