1 : /******************************************************************************
2 : * $Id: pdsdataset.cpp 12658 2007-11-07 23:14:33Z warmerdam $
3 : *
4 : * Project: PDS Driver; Planetary Data System Format
5 : * Purpose: Implementation of NASAKeywordHandler - a class to read
6 : * keyword data from PDS, ISIS2 and ISIS3 data products.
7 : * Author: Frank Warmerdam <warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2006, Frank Warmerdam <warmerdam@pobox.com>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************
30 : * Object Description Language (ODL) is used to encode data labels for PDS
31 : * and other NASA data systems. Refer to Chapter 12 of "PDS Standards
32 : * Reference" at http://pds.jpl.nasa.gov/tools/standards-reference.shtml for
33 : * further details about ODL.
34 : ****************************************************************************/
35 :
36 : #include "cpl_string.h"
37 : #include "nasakeywordhandler.h"
38 :
39 : /************************************************************************/
40 : /* ==================================================================== */
41 : /* NASAKeywordHandler */
42 : /* ==================================================================== */
43 : /************************************************************************/
44 :
45 : /************************************************************************/
46 : /* NASAKeywordHandler() */
47 : /************************************************************************/
48 :
49 11 : NASAKeywordHandler::NASAKeywordHandler()
50 :
51 : {
52 11 : papszKeywordList = NULL;
53 11 : }
54 :
55 : /************************************************************************/
56 : /* ~NASAKeywordHandler() */
57 : /************************************************************************/
58 :
59 11 : NASAKeywordHandler::~NASAKeywordHandler()
60 :
61 : {
62 11 : CSLDestroy( papszKeywordList );
63 11 : papszKeywordList = NULL;
64 11 : }
65 :
66 : /************************************************************************/
67 : /* Ingest() */
68 : /************************************************************************/
69 :
70 11 : int NASAKeywordHandler::Ingest( FILE *fp, int nOffset )
71 :
72 : {
73 : /* -------------------------------------------------------------------- */
74 : /* Read in buffer till we find END all on it's own line. */
75 : /* -------------------------------------------------------------------- */
76 11 : if( VSIFSeekL( fp, nOffset, SEEK_SET ) != 0 )
77 0 : return FALSE;
78 :
79 91 : for( ; TRUE; )
80 : {
81 : const char *pszCheck;
82 : char szChunk[513];
83 :
84 102 : int nBytesRead = VSIFReadL( szChunk, 1, 512, fp );
85 :
86 102 : szChunk[nBytesRead] = '\0';
87 102 : osHeaderText += szChunk;
88 :
89 102 : if( nBytesRead < 512 )
90 4 : break;
91 :
92 98 : if( osHeaderText.size() > 520 )
93 87 : pszCheck = osHeaderText.c_str() + (osHeaderText.size() - 520);
94 : else
95 11 : pszCheck = szChunk;
96 :
97 98 : if( strstr(pszCheck,"\r\nEND\r\n") != NULL
98 : || strstr(pszCheck,"\nEND\n") != NULL
99 : || strstr(pszCheck,"\r\nEnd\r\n") != NULL
100 : || strstr(pszCheck,"\nEnd\n") != NULL )
101 7 : break;
102 : }
103 :
104 11 : pszHeaderNext = osHeaderText.c_str();
105 :
106 : /* -------------------------------------------------------------------- */
107 : /* Process name/value pairs, keeping track of a "path stack". */
108 : /* -------------------------------------------------------------------- */
109 11 : return ReadGroup( "" );
110 : }
111 :
112 : /************************************************************************/
113 : /* ReadGroup() */
114 : /************************************************************************/
115 :
116 70 : int NASAKeywordHandler::ReadGroup( const char *pszPathPrefix )
117 :
118 : {
119 70 : CPLString osName, osValue;
120 :
121 917 : for( ; TRUE; )
122 : {
123 987 : if( !ReadPair( osName, osValue ) )
124 0 : return FALSE;
125 :
126 987 : if( EQUAL(osName,"OBJECT") || EQUAL(osName,"GROUP") )
127 : {
128 59 : if( !ReadGroup( (CPLString(pszPathPrefix) + osValue + ".").c_str() ) )
129 0 : return FALSE;
130 : }
131 928 : else if( EQUALN(osName,"END",3) )
132 : {
133 70 : return TRUE;
134 : }
135 : else
136 : {
137 858 : osName = pszPathPrefix + osName;
138 : papszKeywordList = CSLSetNameValue( papszKeywordList,
139 858 : osName, osValue );
140 : }
141 0 : }
142 : }
143 :
144 : /************************************************************************/
145 : /* ReadPair() */
146 : /* */
147 : /* Read a name/value pair from the input stream. Strip off */
148 : /* white space, ignore comments, split on '='. */
149 : /* Returns TRUE on success. */
150 : /************************************************************************/
151 :
152 987 : int NASAKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue )
153 :
154 : {
155 987 : osName = "";
156 1974 : osValue = "";
157 :
158 987 : if( !ReadWord( osName ) )
159 0 : return FALSE;
160 :
161 987 : SkipWhite();
162 :
163 987 : if( EQUAL(osName,"END") )
164 11 : return TRUE;
165 :
166 976 : if( *pszHeaderNext != '=' )
167 : {
168 : // ISIS3 does not have anything after the end group/object keyword.
169 21 : if( EQUAL(osName,"End_Group") || EQUAL(osName,"End_Object") )
170 21 : return TRUE;
171 : else
172 0 : return FALSE;
173 : }
174 :
175 955 : pszHeaderNext++;
176 :
177 955 : SkipWhite();
178 :
179 955 : osValue = "";
180 :
181 : // Handle value lists like: Name = (Red, Red)
182 955 : if( *pszHeaderNext == '(' )
183 : {
184 51 : CPLString osWord;
185 :
186 51 : while( ReadWord( osWord ) )
187 : {
188 232 : SkipWhite();
189 :
190 232 : osValue += osWord;
191 232 : if( osWord[strlen(osWord)-1] == ')' )
192 51 : break;
193 51 : }
194 : }
195 :
196 : // Handle value lists like: Name = {Red, Red}
197 904 : else if( *pszHeaderNext == '{' )
198 : {
199 2 : CPLString osWord;
200 :
201 2 : while( ReadWord( osWord ) )
202 : {
203 14 : SkipWhite();
204 :
205 14 : osValue += osWord;
206 14 : if( osWord[strlen(osWord)-1] == '}' )
207 2 : break;
208 2 : }
209 : }
210 :
211 : else // Handle more normal "single word" values.
212 : {
213 902 : if( !ReadWord( osValue ) )
214 0 : return FALSE;
215 :
216 : }
217 :
218 955 : SkipWhite();
219 :
220 : // No units keyword?
221 955 : if( *pszHeaderNext != '<' )
222 849 : return TRUE;
223 :
224 : // Append units keyword. For lines that like like this:
225 : // MAP_RESOLUTION = 4.0 <PIXEL/DEGREE>
226 :
227 106 : CPLString osWord;
228 :
229 106 : osValue += " ";
230 :
231 212 : while( ReadWord( osWord ) )
232 : {
233 106 : SkipWhite();
234 :
235 106 : osValue += osWord;
236 106 : if( osWord[strlen(osWord)-1] == '>' )
237 106 : break;
238 : }
239 :
240 106 : return TRUE;
241 : }
242 :
243 : /************************************************************************/
244 : /* ReadWord() */
245 : /* Returns TRUE on success */
246 : /************************************************************************/
247 :
248 2241 : int NASAKeywordHandler::ReadWord( CPLString &osWord )
249 :
250 : {
251 2241 : osWord = "";
252 :
253 2241 : SkipWhite();
254 :
255 4482 : if( !(*pszHeaderNext != '\0'
256 : && *pszHeaderNext != '='
257 : && !isspace((unsigned char)*pszHeaderNext)) )
258 0 : return FALSE;
259 :
260 : /* Extract a text string delimited by '\"' */
261 : /* Convert newlines (CR or LF) within quotes. While text strings
262 : support them as per ODL, the keyword list doesn't want them */
263 2241 : if( *pszHeaderNext == '"' )
264 : {
265 210 : osWord += *(pszHeaderNext++);
266 3851 : while( *pszHeaderNext != '"' )
267 : {
268 3431 : if( *pszHeaderNext == '\0' )
269 0 : return FALSE;
270 3431 : if( *pszHeaderNext == '\n' )
271 : {
272 14 : osWord += "\\n";
273 14 : pszHeaderNext++;
274 14 : continue;
275 : }
276 3417 : if( *pszHeaderNext == '\r' )
277 : {
278 12 : osWord += "\\r";
279 12 : pszHeaderNext++;
280 12 : continue;
281 : }
282 3405 : osWord += *(pszHeaderNext++);
283 : }
284 210 : osWord += *(pszHeaderNext++);
285 210 : return TRUE;
286 : }
287 : /* Extract a symbol string */
288 : /* These are expected to not have
289 : '\'' (delimiters),
290 : format effectors (should fit on a single line) or
291 : control characters. */
292 2031 : if( *pszHeaderNext == '\'' )
293 : {
294 0 : osWord += *(pszHeaderNext++);
295 0 : while( *pszHeaderNext != '\'' )
296 : {
297 0 : if( *pszHeaderNext == '\0' )
298 0 : return FALSE;
299 :
300 0 : osWord += *(pszHeaderNext++);
301 : }
302 0 : osWord += *(pszHeaderNext++);
303 0 : return TRUE;
304 : }
305 :
306 26846 : while( *pszHeaderNext != '\0'
307 : && *pszHeaderNext != '='
308 : && !isspace((unsigned char)*pszHeaderNext) )
309 : {
310 22784 : osWord += *pszHeaderNext;
311 22784 : pszHeaderNext++;
312 : }
313 :
314 2031 : return TRUE;
315 : }
316 :
317 : /************************************************************************/
318 : /* SkipWhite() */
319 : /* Skip white spaces and C style comments */
320 : /************************************************************************/
321 :
322 21471 : void NASAKeywordHandler::SkipWhite()
323 :
324 : {
325 15981 : for( ; TRUE; )
326 : {
327 : // Skip C style comments
328 21471 : if( *pszHeaderNext == '/' && pszHeaderNext[1] == '*' )
329 : {
330 121 : pszHeaderNext += 2;
331 :
332 6480 : while( *pszHeaderNext != '\0'
333 : && (*pszHeaderNext != '*'
334 228 : || pszHeaderNext[1] != '/' ) )
335 : {
336 6010 : pszHeaderNext++;
337 : }
338 :
339 121 : pszHeaderNext += 2;
340 121 : continue;
341 : }
342 :
343 : // Skip # style comments
344 37210 : if( (*pszHeaderNext == 10 || *pszHeaderNext == 13 ||
345 : *pszHeaderNext == ' ' || *pszHeaderNext == '\t' )
346 15860 : && pszHeaderNext[1] == '#' )
347 : {
348 4 : pszHeaderNext += 2;
349 :
350 : // consume till end of line.
351 216 : while( *pszHeaderNext != '\0'
352 : && *pszHeaderNext != 10
353 : && *pszHeaderNext != 13 )
354 : {
355 208 : pszHeaderNext++;
356 : }
357 4 : continue;
358 : }
359 :
360 : // Skip white space (newline, space, tab, etc )
361 21346 : if( isspace( (unsigned char)*pszHeaderNext ) )
362 : {
363 15856 : pszHeaderNext++;
364 15856 : continue;
365 : }
366 :
367 : // not white space, return.
368 : return;
369 : }
370 : }
371 :
372 : /************************************************************************/
373 : /* GetKeyword() */
374 : /************************************************************************/
375 :
376 371 : const char *NASAKeywordHandler::GetKeyword( const char *pszPath,
377 : const char *pszDefault )
378 :
379 : {
380 : const char *pszResult;
381 :
382 371 : pszResult = CSLFetchNameValue( papszKeywordList, pszPath );
383 371 : if( pszResult == NULL )
384 116 : return pszDefault;
385 : else
386 255 : return pszResult;
387 : }
388 :
|