1 : /******************************************************************************
2 : * $Id: EnvisatFile.c 22619 2011-06-29 20:54:01Z rouault $
3 : *
4 : * Project: APP ENVISAT Support
5 : * Purpose: Low Level Envisat file access (read/write) API.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2001, Atlantis Scientific, Inc.
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 : #ifndef APP_BUILD
31 : # define GDAL_BUILD
32 : # include "cpl_conv.h"
33 : # include "EnvisatFile.h"
34 :
35 : CPL_CVSID("$Id: EnvisatFile.c 22619 2011-06-29 20:54:01Z rouault $");
36 :
37 : #else
38 : # include "APP/app.h"
39 : # include "util/Files/EnvisatFile.h"
40 : #endif
41 :
42 : typedef struct
43 : {
44 : char *ds_name;
45 : char *ds_type;
46 : char *filename;
47 : int ds_offset;
48 : int ds_size;
49 : int num_dsr;
50 : int dsr_size;
51 : } EnvisatDatasetInfo;
52 :
53 : typedef struct
54 : {
55 : char *key;
56 : char *value;
57 : char *units;
58 : char *literal_line;
59 : int value_offset;
60 : } EnvisatNameValue;
61 :
62 : struct EnvisatFile_tag
63 : {
64 : FILE *fp;
65 : char *filename;
66 : int updatable;
67 : int header_dirty;
68 : int dsd_offset;
69 :
70 : int mph_count;
71 : EnvisatNameValue **mph_entries;
72 :
73 : int sph_count;
74 : EnvisatNameValue **sph_entries;
75 :
76 : int ds_count;
77 : EnvisatDatasetInfo **ds_info;
78 :
79 : };
80 :
81 : #ifdef GDAL_BUILD
82 : # define SUCCESS 0
83 : # define FAILURE 1
84 : # define SendError( text ) CPLError( CE_Failure, CPLE_AppDefined, "%s", text )
85 : #endif
86 :
87 : #define MPH_SIZE 1247
88 :
89 : /*
90 : * API For handling name/value lists.
91 : */
92 : int S_NameValueList_Parse( const char *text, int text_offset,
93 : int *entry_count,
94 : EnvisatNameValue ***entries );
95 : void S_NameValueList_Destroy( int *entry_count,
96 : EnvisatNameValue ***entries );
97 : int S_NameValueList_FindKey( const char *key,
98 : int entry_count,
99 : EnvisatNameValue **entries );
100 : const char *S_NameValueList_FindValue( const char *key,
101 : int entry_count,
102 : EnvisatNameValue **entries,
103 : const char * default_value );
104 :
105 : int S_NameValueList_Rewrite( FILE *fp, int entry_count,
106 : EnvisatNameValue **entries );
107 :
108 : EnvisatNameValue *
109 : S_EnivsatFile_FindNameValue( EnvisatFile *self,
110 : EnvisatFile_HeaderFlag mph_or_sph,
111 : const char * key );
112 :
113 :
114 :
115 :
116 : /*-----------------------------------------------------------------------------
117 :
118 : Name:
119 : Envisat_SetupLevel0
120 :
121 : Purpose:
122 : Patch up missing information about SPH, and datasets for incomplete
123 : level 0 signal datasets.
124 :
125 : Description:
126 :
127 : Inputs:
128 : self -- Envisat file handle.
129 :
130 : Outputs:
131 :
132 : Returns:
133 : SUCCESS or FAILURE
134 :
135 : -----------------------------------------------------------------------------*/
136 :
137 0 : static int EnvisatFile_SetupLevel0( EnvisatFile *self )
138 :
139 : {
140 : int file_length;
141 : unsigned char header[68];
142 : EnvisatDatasetInfo *ds_info;
143 :
144 0 : self->dsd_offset = 0;
145 0 : self->ds_count = 1;
146 0 : self->ds_info = (EnvisatDatasetInfo **)
147 0 : calloc(sizeof(EnvisatDatasetInfo*),self->ds_count);
148 :
149 0 : if( self->ds_info == NULL )
150 0 : return FAILURE;
151 :
152 : /*
153 : * Figure out how long the file is.
154 : */
155 :
156 0 : fseek( self->fp, 0, SEEK_END );
157 0 : file_length = (int) ftell( self->fp );
158 :
159 : /*
160 : * Read the first record header, and verify the well known values.
161 : */
162 0 : fseek( self->fp, 3203, SEEK_SET );
163 0 : fread( header, 68, 1, self->fp );
164 :
165 0 : if( header[38] != 0 || header[39] != 0x1d
166 0 : || header[40] != 0 || header[41] != 0x54 )
167 : {
168 0 : SendError( "Didn't get expected Data Field Header Length, or Mode ID\n"
169 : "values for the first data record." );
170 0 : return FAILURE;
171 : }
172 :
173 : /*
174 : * Then build the dataset into structure from that.
175 : */
176 0 : ds_info = (EnvisatDatasetInfo *) calloc(sizeof(EnvisatDatasetInfo),1);
177 :
178 0 : ds_info->ds_name = strdup( "ASAR SOURCE PACKETS " );
179 0 : ds_info->ds_type = strdup( "M" );
180 0 : ds_info->filename = strdup( " " );
181 0 : ds_info->ds_offset = 3203;
182 0 : ds_info->dsr_size = -1;
183 0 : ds_info->num_dsr = 0;
184 0 : ds_info->ds_size = file_length - ds_info->ds_offset;
185 :
186 0 : self->ds_info[0] = ds_info;
187 :
188 0 : return SUCCESS;
189 : }
190 :
191 : /*-----------------------------------------------------------------------------
192 :
193 : Name:
194 : Envisat_Open
195 :
196 : Purpose:
197 : Open an ENVISAT formatted file, and read all headers.
198 :
199 : Description:
200 :
201 : Inputs:
202 : filename -- name of Envisat file.
203 : mode -- either "r" for read access, or "r+" for read/write access.
204 :
205 : Outputs:
206 : self -- file handle, NULL on FAILURE.
207 :
208 : Returns:
209 : SUCCESS or FAILURE
210 :
211 : -----------------------------------------------------------------------------*/
212 :
213 13 : int EnvisatFile_Open( EnvisatFile **self_ptr,
214 : const char *filename,
215 : const char *mode )
216 :
217 : {
218 : FILE *fp;
219 : EnvisatFile *self;
220 : char mph_data[1248];
221 : char *sph_data, *ds_data;
222 : int sph_size, num_dsd, dsd_size, i;
223 :
224 13 : *self_ptr = NULL;
225 :
226 : /*
227 : * Check for legal mode argument. Force to be binary for correct
228 : * operation on DOS file systems.
229 : */
230 13 : if( strcmp(mode,"r") == 0 )
231 13 : mode = "rb";
232 0 : else if( strcmp(mode,"r+") == 0 )
233 0 : mode = "rb+";
234 : else
235 : {
236 0 : SendError( "Illegal mode value used in EnvisatFile_Open(), only "
237 : "\"r\" and \"r+\" are supported." );
238 0 : return FAILURE;
239 : }
240 :
241 : /*
242 : * Try to open the file, and report failure.
243 : */
244 :
245 13 : fp = fopen( filename, mode );
246 :
247 13 : if( fp == NULL )
248 : {
249 : char error_buf[2048];
250 :
251 0 : sprintf( error_buf,
252 : "Unable to open file \"%s\" in EnvisatFile_Open().",
253 : filename );
254 :
255 0 : SendError( error_buf );
256 0 : return FAILURE;
257 : }
258 :
259 : /*
260 : * Create, and initialize the EnvisatFile structure.
261 : */
262 13 : self = (EnvisatFile *) calloc(sizeof(EnvisatFile),1);
263 13 : if( self == NULL )
264 0 : return FAILURE;
265 :
266 13 : self->fp = fp;
267 13 : self->filename = strdup( filename );
268 13 : self->header_dirty = 0;
269 13 : self->updatable = (strcmp(mode,"rb+") == 0);
270 :
271 : /*
272 : * Read the MPH, and process it as a group of name/value pairs.
273 : */
274 :
275 13 : if( fread( mph_data, 1, MPH_SIZE, fp ) != MPH_SIZE )
276 : {
277 0 : free( self );
278 0 : SendError( "fread() for mph failed." );
279 0 : return FAILURE;
280 : }
281 :
282 13 : mph_data[MPH_SIZE] = '\0';
283 13 : if( S_NameValueList_Parse( mph_data, 0,
284 : &(self->mph_count),
285 : &(self->mph_entries) ) == FAILURE )
286 0 : return FAILURE;
287 :
288 : /*
289 : * Is this an incomplete level 0 file?
290 : */
291 13 : if( EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", -1 ) == 0
292 13 : && strncmp(EnvisatFile_GetKeyValueAsString( self, MPH, "PRODUCT", ""),
293 0 : "ASA_IM__0P", 10) == 0 )
294 : {
295 :
296 0 : if( EnvisatFile_SetupLevel0( self ) == FAILURE )
297 : {
298 0 : EnvisatFile_Close( self );
299 0 : return FAILURE;
300 : }
301 : else
302 : {
303 0 : *self_ptr = self;
304 0 : return SUCCESS;
305 : }
306 : }
307 :
308 : /*
309 : * Read the SPH, and process it as a group of name/value pairs.
310 : */
311 13 : sph_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", 0 );
312 :
313 13 : if( sph_size == 0 )
314 : {
315 0 : SendError( "File does not appear to have SPH,"
316 : " SPH_SIZE not set, or zero." );
317 0 : return FAILURE;
318 : }
319 :
320 13 : sph_data = (char *) malloc(sph_size + 1 );
321 13 : if( sph_data == NULL )
322 0 : return FAILURE;
323 :
324 13 : if( (int) fread( sph_data, 1, sph_size, fp ) != sph_size )
325 : {
326 0 : free( self );
327 0 : SendError( "fread() for sph failed." );
328 0 : return FAILURE;
329 : }
330 :
331 13 : sph_data[sph_size] = '\0';
332 13 : ds_data = strstr(sph_data,"DS_NAME");
333 13 : if( ds_data != NULL )
334 : {
335 13 : self->dsd_offset = (int) (ds_data - sph_data) + MPH_SIZE;
336 13 : *(ds_data-1) = '\0';
337 : }
338 :
339 13 : if( S_NameValueList_Parse( sph_data, MPH_SIZE,
340 : &(self->sph_count),
341 : &(self->sph_entries) ) == FAILURE )
342 0 : return FAILURE;
343 :
344 : /*
345 : * Parse the Dataset Definitions.
346 : */
347 13 : num_dsd = EnvisatFile_GetKeyValueAsInt( self, MPH, "NUM_DSD", 0 );
348 13 : dsd_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "DSD_SIZE", 0 );
349 :
350 13 : if( num_dsd > 0 && ds_data == NULL )
351 : {
352 0 : SendError( "DSDs indicated in MPH, but not found in SPH." );
353 0 : return FAILURE;
354 : }
355 :
356 13 : self->ds_info = (EnvisatDatasetInfo **)
357 : calloc(sizeof(EnvisatDatasetInfo*),num_dsd);
358 13 : if( self->ds_info == NULL )
359 0 : return FAILURE;
360 :
361 373 : for( i = 0; i < num_dsd; i++ )
362 : {
363 360 : int dsdh_count = 0;
364 360 : EnvisatNameValue **dsdh_entries = NULL;
365 : char *dsd_data;
366 : EnvisatDatasetInfo *ds_info;
367 :
368 : /*
369 : * We parse each DSD grouping into a name/value list.
370 : */
371 360 : dsd_data = ds_data + i * dsd_size;
372 360 : dsd_data[dsd_size-1] = '\0';
373 :
374 360 : if( S_NameValueList_Parse( dsd_data, 0,
375 : &dsdh_count, &dsdh_entries ) == FAILURE )
376 0 : return FAILURE;
377 :
378 : /*
379 : * Then build the dataset into structure from that.
380 : */
381 360 : ds_info = (EnvisatDatasetInfo *) calloc(sizeof(EnvisatDatasetInfo),1);
382 :
383 360 : ds_info->ds_name = strdup(
384 : S_NameValueList_FindValue( "DS_NAME",
385 : dsdh_count, dsdh_entries, "" ));
386 360 : ds_info->ds_type = strdup(
387 : S_NameValueList_FindValue( "DS_TYPE",
388 : dsdh_count, dsdh_entries, "" ));
389 360 : ds_info->filename = strdup(
390 : S_NameValueList_FindValue( "FILENAME",
391 : dsdh_count, dsdh_entries, "" ));
392 360 : ds_info->ds_offset = atoi(
393 : S_NameValueList_FindValue( "DS_OFFSET",
394 : dsdh_count, dsdh_entries, "0" ));
395 360 : ds_info->ds_size = atoi(
396 : S_NameValueList_FindValue( "DS_SIZE",
397 : dsdh_count, dsdh_entries, "0" ));
398 360 : ds_info->num_dsr = atoi(
399 : S_NameValueList_FindValue( "NUM_DSR",
400 : dsdh_count, dsdh_entries, "0" ));
401 360 : ds_info->dsr_size = atoi(
402 : S_NameValueList_FindValue( "DSR_SIZE",
403 : dsdh_count, dsdh_entries, "0" ));
404 :
405 360 : S_NameValueList_Destroy( &dsdh_count, &dsdh_entries );
406 :
407 360 : self->ds_info[i] = ds_info;
408 360 : self->ds_count++;
409 : }
410 :
411 13 : free( sph_data );
412 :
413 : /*
414 : * Return successfully.
415 : */
416 13 : *self_ptr = self;
417 :
418 13 : return SUCCESS;
419 : }
420 :
421 : /*-----------------------------------------------------------------------------
422 :
423 : Name:
424 : EnvisatFile_Create
425 :
426 : Purpose:
427 : Create a new ENVISAT formatted file based on a template file.
428 :
429 : Description:
430 :
431 : Inputs:
432 : filename -- name of Envisat file.
433 : template_file -- name of envisat file header to utilize as template.
434 :
435 : Outputs:
436 : self -- file handle, NULL on FAILURE.
437 :
438 : Returns:
439 : SUCCESS or FAILURE
440 :
441 : -----------------------------------------------------------------------------*/
442 :
443 0 : int EnvisatFile_Create( EnvisatFile **self_ptr,
444 : const char *filename,
445 : const char *template_file )
446 :
447 : {
448 : int template_size;
449 : char *template_data;
450 : FILE *fp;
451 :
452 : /*
453 : * Try to open the template file, and read it into memory.
454 : */
455 :
456 0 : fp = fopen( template_file, "rb" );
457 :
458 0 : if( fp == NULL )
459 : {
460 : char error_buf[2048];
461 :
462 0 : sprintf( error_buf,
463 : "Unable to open file \"%s\" in EnvisatFile_Create().",
464 : template_file );
465 :
466 0 : SendError( error_buf );
467 0 : return FAILURE;
468 : }
469 :
470 0 : fseek( fp, 0, SEEK_END );
471 0 : template_size = (int) ftell( fp );
472 :
473 0 : template_data = (char *) malloc(template_size);
474 :
475 0 : fseek( fp, 0, SEEK_SET );
476 0 : fread( template_data, template_size, 1, fp );
477 0 : fclose( fp );
478 :
479 : /*
480 : * Try to write the template out to the new filename.
481 : */
482 :
483 0 : fp = fopen( filename, "wb" );
484 0 : if( fp == NULL )
485 : {
486 : char error_buf[2048];
487 :
488 0 : sprintf( error_buf,
489 : "Unable to open file \"%s\" in EnvisatFile_Create().",
490 : filename );
491 :
492 0 : SendError( error_buf );
493 0 : return FAILURE;
494 : }
495 :
496 0 : fwrite( template_data, template_size, 1, fp );
497 0 : fclose( fp );
498 :
499 0 : free( template_data );
500 :
501 : /*
502 : * Now just open the file normally.
503 : */
504 :
505 0 : return EnvisatFile_Open( self_ptr, filename, "r+" );
506 : }
507 :
508 : /*-----------------------------------------------------------------------------
509 :
510 : Name:
511 : EnvisatFile_GetCurrentLength
512 :
513 : Purpose:
514 : Fetch the current file length.
515 :
516 : Description:
517 : The length is computed by scanning the dataset definitions, not the
518 : physical file length.
519 :
520 : Inputs:
521 : self -- the file to operate on.
522 :
523 : Outputs:
524 :
525 : Returns:
526 : Returns length or -1 on failure.
527 :
528 : -----------------------------------------------------------------------------*/
529 :
530 0 : int EnvisatFile_GetCurrentLength( EnvisatFile *self )
531 :
532 : {
533 : int length;
534 : int ds;
535 : int ds_offset;
536 : int ds_size;
537 :
538 0 : length = MPH_SIZE
539 : + EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", 0 );
540 :
541 0 : for( ds = 0;
542 0 : EnvisatFile_GetDatasetInfo( self, ds, NULL, NULL, NULL,
543 : &ds_offset, &ds_size, NULL, NULL )
544 : != FAILURE;
545 0 : ds++ )
546 : {
547 0 : if( ds_offset != 0 && (ds_offset+ds_size) > length )
548 0 : length = ds_offset + ds_size;
549 : }
550 :
551 0 : return length;
552 : }
553 :
554 : /*-----------------------------------------------------------------------------
555 :
556 : Name:
557 : EnvisatFile_RewriteHeader
558 :
559 : Purpose:
560 : Update the envisat file header on disk to match the in-memory image.
561 :
562 : Description:
563 :
564 : Inputs:
565 : self -- handle for file to close.
566 :
567 : Outputs:
568 :
569 : Returns:
570 : SUCCESS or FAILURE.
571 :
572 : -----------------------------------------------------------------------------*/
573 :
574 0 : static int EnvisatFile_RewriteHeader( EnvisatFile *self )
575 :
576 : {
577 : int dsd, dsd_size;
578 :
579 : /*
580 : * Rewrite MPH and SPH headers.
581 : */
582 0 : if( S_NameValueList_Rewrite( self->fp,
583 : self->mph_count, self->mph_entries ) == FAILURE )
584 0 : return FAILURE;
585 :
586 0 : if( S_NameValueList_Rewrite( self->fp,
587 : self->sph_count, self->sph_entries ) == FAILURE )
588 0 : return FAILURE;
589 :
590 : /*
591 : * Rewrite DSDs. We actually have to read each, and reparse to set
592 : * the individual parameters properly.
593 : */
594 0 : dsd_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "DSD_SIZE", 0 );
595 0 : if( dsd_size == 0 )
596 0 : return FAILURE;
597 :
598 0 : for( dsd = 0; dsd < self->ds_count; dsd++ )
599 : {
600 : char *dsd_text;
601 0 : int dsdh_count = 0, key_index;
602 0 : EnvisatNameValue **dsdh_entries = NULL;
603 :
604 0 : dsd_text = (char *) calloc(1,dsd_size+1);
605 0 : if( fseek( self->fp, self->dsd_offset + dsd * dsd_size,
606 : SEEK_SET ) != 0 )
607 : {
608 0 : SendError( "fseek() failed in EnvisatFile_RewriteHeader()" );
609 0 : return FAILURE;
610 : }
611 :
612 0 : if( (int) fread( dsd_text, 1, dsd_size, self->fp ) != dsd_size )
613 : {
614 0 : SendError( "fread() failed in EnvisatFile_RewriteHeader()" );
615 0 : return FAILURE;
616 : }
617 :
618 0 : if( S_NameValueList_Parse( dsd_text, self->dsd_offset + dsd*dsd_size,
619 : &dsdh_count, &dsdh_entries ) == FAILURE )
620 0 : return FAILURE;
621 :
622 0 : free( dsd_text );
623 :
624 0 : key_index = S_NameValueList_FindKey( "DS_OFFSET",
625 : dsdh_count, dsdh_entries );
626 0 : if( key_index == -1 )
627 0 : continue;
628 :
629 0 : sprintf( dsdh_entries[key_index]->value, "%+021d",
630 0 : self->ds_info[dsd]->ds_offset );
631 :
632 0 : key_index = S_NameValueList_FindKey( "DS_SIZE",
633 : dsdh_count, dsdh_entries );
634 0 : sprintf( dsdh_entries[key_index]->value, "%+021d",
635 0 : self->ds_info[dsd]->ds_size );
636 :
637 0 : key_index = S_NameValueList_FindKey( "NUM_DSR",
638 : dsdh_count, dsdh_entries );
639 0 : sprintf( dsdh_entries[key_index]->value, "%+011d",
640 0 : self->ds_info[dsd]->num_dsr );
641 :
642 0 : key_index = S_NameValueList_FindKey( "DSR_SIZE",
643 : dsdh_count, dsdh_entries );
644 0 : sprintf( dsdh_entries[key_index]->value, "%+011d",
645 0 : self->ds_info[dsd]->dsr_size );
646 :
647 0 : if( S_NameValueList_Rewrite( self->fp, dsdh_count, dsdh_entries )
648 : == FAILURE )
649 0 : return FAILURE;
650 :
651 0 : S_NameValueList_Destroy( &dsdh_count, &dsdh_entries );
652 : }
653 :
654 0 : self->header_dirty = 0;
655 :
656 0 : return SUCCESS;
657 : }
658 :
659 : /*-----------------------------------------------------------------------------
660 :
661 : Name:
662 : EnvisatFile_Close
663 :
664 : Purpose:
665 : Close an ENVISAT formatted file, releasing all associated resources.
666 :
667 : Description:
668 :
669 : Inputs:
670 : self -- handle for file to close.
671 :
672 : Outputs:
673 :
674 : Returns:
675 :
676 :
677 : -----------------------------------------------------------------------------*/
678 :
679 13 : void EnvisatFile_Close( EnvisatFile *self )
680 :
681 : {
682 : int i;
683 :
684 : /*
685 : * Do we need to write out the header information?
686 : */
687 13 : if( self->header_dirty )
688 0 : EnvisatFile_RewriteHeader( self );
689 :
690 : /*
691 : * Close file.
692 : */
693 13 : if( self->fp != NULL )
694 13 : fclose( self->fp );
695 :
696 : /*
697 : * Clean up data structures.
698 : */
699 13 : S_NameValueList_Destroy( &(self->mph_count), &(self->mph_entries) );
700 13 : S_NameValueList_Destroy( &(self->sph_count), &(self->sph_entries) );
701 :
702 373 : for( i = 0; i < self->ds_count; i++ )
703 : {
704 360 : if( self->ds_info != NULL && self->ds_info[i] != NULL )
705 : {
706 360 : free( self->ds_info[i]->ds_name );
707 360 : free( self->ds_info[i]->ds_type );
708 360 : free( self->ds_info[i]->filename );
709 360 : free( self->ds_info[i] );
710 : }
711 : }
712 13 : if( self->ds_info != NULL )
713 13 : free( self->ds_info );
714 13 : if( self->filename != NULL )
715 13 : free( self->filename );
716 :
717 13 : free( self );
718 13 : }
719 :
720 : /*-----------------------------------------------------------------------------
721 :
722 : Name:
723 : EnvisatFile_GetFilename
724 :
725 : Purpose:
726 : Fetch name of this Envisat file.
727 :
728 : Description:
729 :
730 : Inputs:
731 : self -- handle for file to get name of.
732 :
733 : Outputs:
734 :
735 : Returns:
736 : const pointer to internal copy of the filename. Do not alter or free.
737 :
738 :
739 : -----------------------------------------------------------------------------*/
740 :
741 0 : const char *EnvisatFile_GetFilename( EnvisatFile *self )
742 :
743 : {
744 0 : return self->filename;
745 : }
746 :
747 : /*-----------------------------------------------------------------------------
748 :
749 : Name:
750 : EnvisatFile_GetKeyByIndex()
751 :
752 : Purpose:
753 : Fetch the key with the indicated index.
754 :
755 : Description:
756 : This function can be used to "discover" the set of available keys by
757 : by scanning with index values starting at zero and ending when a NULL
758 : is returned.
759 :
760 : Inputs:
761 : self -- the file to be searched.
762 : mph_or_sph -- Either MPH or SPH depending on the header to be searched.
763 : key_index -- key index, from zero to number of keys-1.
764 :
765 : Outputs:
766 :
767 : Returns:
768 : pointer to key name or NULL on failure.
769 :
770 : -----------------------------------------------------------------------------*/
771 :
772 926 : const char *EnvisatFile_GetKeyByIndex( EnvisatFile *self,
773 : EnvisatFile_HeaderFlag mph_or_sph,
774 : int key_index )
775 :
776 : {
777 : int entry_count;
778 : EnvisatNameValue **entries;
779 :
780 : /*
781 : * Select source list.
782 : */
783 926 : if( mph_or_sph == MPH )
784 : {
785 455 : entry_count = self->mph_count;
786 455 : entries = self->mph_entries;
787 : }
788 : else
789 : {
790 471 : entry_count = self->sph_count;
791 471 : entries = self->sph_entries;
792 : }
793 :
794 926 : if( key_index < 0 || key_index >= entry_count )
795 26 : return NULL;
796 : else
797 900 : return entries[key_index]->key;
798 : }
799 :
800 : /*-----------------------------------------------------------------------------
801 :
802 : Name:
803 : EnvisatFile_GetKeyValueAsString()
804 :
805 : Purpose:
806 : Fetch the value associated with the indicated key as a string.
807 :
808 : Description:
809 :
810 : Inputs:
811 : self -- the file to be searched.
812 : mph_or_sph -- Either MPH or SPH depending on the header to be searched.
813 : key -- the key (name) to be searched for.
814 : default_value -- the value to return if the key is not found.
815 :
816 : Outputs:
817 :
818 : Returns:
819 : pointer to value string, or default_value if not found.
820 :
821 : -----------------------------------------------------------------------------*/
822 :
823 952 : const char *EnvisatFile_GetKeyValueAsString( EnvisatFile *self,
824 : EnvisatFile_HeaderFlag mph_or_sph,
825 : const char *key,
826 : const char *default_value )
827 :
828 : {
829 : int entry_count, key_index;
830 : EnvisatNameValue **entries;
831 :
832 : /*
833 : * Select source list.
834 : */
835 952 : if( mph_or_sph == MPH )
836 : {
837 468 : entry_count = self->mph_count;
838 468 : entries = self->mph_entries;
839 : }
840 : else
841 : {
842 484 : entry_count = self->sph_count;
843 484 : entries = self->sph_entries;
844 : }
845 :
846 : /*
847 : * Find and return the value.
848 : */
849 952 : key_index = S_NameValueList_FindKey( key, entry_count, entries );
850 952 : if( key_index == -1 )
851 14 : return default_value;
852 : else
853 938 : return entries[key_index]->value;
854 : }
855 :
856 : /*-----------------------------------------------------------------------------
857 :
858 : Name:
859 : EnvisatFile_SetKeyValueAsString()
860 :
861 : Purpose:
862 : Set the value associated with the indicated key as a string.
863 :
864 : Description:
865 :
866 : Inputs:
867 : self -- the file to be searched.
868 : mph_or_sph -- Either MPH or SPH depending on the header to be searched.
869 : key -- the key (name) to be searched for.
870 : value -- the value to assign.
871 :
872 : Outputs:
873 :
874 : Returns:
875 : SUCCESS or FAILURE.
876 :
877 : -----------------------------------------------------------------------------*/
878 :
879 0 : int EnvisatFile_SetKeyValueAsString( EnvisatFile *self,
880 : EnvisatFile_HeaderFlag mph_or_sph,
881 : const char *key,
882 : const char *value )
883 :
884 : {
885 : int entry_count, key_index;
886 : EnvisatNameValue **entries;
887 :
888 0 : if( !self->updatable )
889 : {
890 0 : SendError( "File not opened for update access." );
891 0 : return FAILURE;
892 : }
893 :
894 : /*
895 : * Select source list.
896 : */
897 0 : if( mph_or_sph == MPH )
898 : {
899 0 : entry_count = self->mph_count;
900 0 : entries = self->mph_entries;
901 : }
902 : else
903 : {
904 0 : entry_count = self->sph_count;
905 0 : entries = self->sph_entries;
906 : }
907 :
908 : /*
909 : * Find and return the value.
910 : */
911 0 : key_index = S_NameValueList_FindKey( key, entry_count, entries );
912 0 : if( key_index == -1 )
913 : {
914 : char error_buf[2048];
915 :
916 0 : sprintf( error_buf,
917 : "Unable to set header field \"%s\", field not found.",
918 : key );
919 :
920 0 : SendError( error_buf );
921 0 : return FAILURE;
922 : }
923 :
924 0 : self->header_dirty = 1;
925 0 : if( strlen(value) > strlen(entries[key_index]->value) )
926 : {
927 0 : strncpy( entries[key_index]->value, value,
928 0 : strlen(entries[key_index]->value) );
929 : }
930 : else
931 : {
932 0 : memset( entries[key_index]->value, ' ',
933 0 : strlen(entries[key_index]->value) );
934 0 : strncpy( entries[key_index]->value, value, strlen(value) );
935 : }
936 :
937 0 : return SUCCESS;
938 : }
939 :
940 : /*-----------------------------------------------------------------------------
941 :
942 : Name:
943 : EnvisatFile_GetKeyValueAsInt()
944 :
945 : Purpose:
946 : Fetch the value associated with the indicated key as an integer.
947 :
948 : Description:
949 :
950 : Inputs:
951 : self -- the file to be searched.
952 : mph_or_sph -- Either MPH or SPH depending on the header to be searched.
953 : key -- the key (name) to be searched for.
954 : default_value -- the value to return if the key is not found.
955 :
956 : Outputs:
957 :
958 : Returns:
959 : key value, or default_value if key not found.
960 :
961 : -----------------------------------------------------------------------------*/
962 :
963 79 : int EnvisatFile_GetKeyValueAsInt( EnvisatFile *self,
964 : EnvisatFile_HeaderFlag mph_or_sph,
965 : const char *key,
966 : int default_value )
967 :
968 : {
969 : int entry_count, key_index;
970 : EnvisatNameValue **entries;
971 :
972 : /*
973 : * Select source list.
974 : */
975 79 : if( mph_or_sph == MPH )
976 : {
977 52 : entry_count = self->mph_count;
978 52 : entries = self->mph_entries;
979 : }
980 : else
981 : {
982 27 : entry_count = self->sph_count;
983 27 : entries = self->sph_entries;
984 : }
985 :
986 : /*
987 : * Find and return the value.
988 : */
989 79 : key_index = S_NameValueList_FindKey( key, entry_count, entries );
990 79 : if( key_index == -1 )
991 0 : return default_value;
992 : else
993 79 : return atoi(entries[key_index]->value);
994 : }
995 :
996 : /*-----------------------------------------------------------------------------
997 :
998 : Name:
999 : EnvisatFile_SetKeyValueAsInt()
1000 :
1001 : Purpose:
1002 : Set the value associated with the indicated key as an integer.
1003 :
1004 : Description:
1005 :
1006 : Inputs:
1007 : self -- the file to be searched.
1008 : mph_or_sph -- Either MPH or SPH depending on the header to be searched.
1009 : key -- the key (name) to be searched for.
1010 : value -- the value to assign.
1011 :
1012 : Outputs:
1013 :
1014 : Returns:
1015 : SUCCESS or FAILURE.
1016 :
1017 : -----------------------------------------------------------------------------*/
1018 :
1019 0 : int EnvisatFile_SetKeyValueAsInt( EnvisatFile *self,
1020 : EnvisatFile_HeaderFlag mph_or_sph,
1021 : const char *key,
1022 : int value )
1023 :
1024 : {
1025 : char format[32], string_value[128];
1026 : const char *prototype_value;
1027 :
1028 :
1029 0 : prototype_value = EnvisatFile_GetKeyValueAsString( self, mph_or_sph, key, NULL);
1030 0 : if( prototype_value == NULL )
1031 : {
1032 : char error_buf[2048];
1033 :
1034 0 : sprintf( error_buf,
1035 : "Unable to set header field \"%s\", field not found.",
1036 : key );
1037 :
1038 0 : SendError( error_buf );
1039 0 : return FAILURE;
1040 : }
1041 :
1042 0 : sprintf( format, "%%+0%dd", (int) strlen(prototype_value) );
1043 0 : sprintf( string_value, format, value );
1044 :
1045 0 : return EnvisatFile_SetKeyValueAsString( self, mph_or_sph, key, string_value );
1046 : }
1047 :
1048 : /*-----------------------------------------------------------------------------
1049 :
1050 : Name:
1051 : EnvisatFile_GetKeyValueAsDouble()
1052 :
1053 : Purpose:
1054 : Fetch the value associated with the indicated key as a double.
1055 :
1056 : Description:
1057 :
1058 : Inputs:
1059 : self -- the file to be searched.
1060 : mph_or_sph -- Either MPH or SPH depending on the header to be searched.
1061 : key -- the key (name) to be searched for.
1062 : default_value -- the value to return if the key is not found.
1063 :
1064 : Outputs:
1065 :
1066 : Returns:
1067 : key value, or default_value if key not found.
1068 :
1069 : -----------------------------------------------------------------------------*/
1070 :
1071 0 : double EnvisatFile_GetKeyValueAsDouble( EnvisatFile *self,
1072 : EnvisatFile_HeaderFlag mph_or_sph,
1073 : const char *key,
1074 : double default_value )
1075 :
1076 : {
1077 : int entry_count, key_index;
1078 : EnvisatNameValue **entries;
1079 :
1080 : /*
1081 : * Select source list.
1082 : */
1083 0 : if( mph_or_sph == MPH )
1084 : {
1085 0 : entry_count = self->mph_count;
1086 0 : entries = self->mph_entries;
1087 : }
1088 : else
1089 : {
1090 0 : entry_count = self->sph_count;
1091 0 : entries = self->sph_entries;
1092 : }
1093 :
1094 : /*
1095 : * Find and return the value.
1096 : */
1097 0 : key_index = S_NameValueList_FindKey( key, entry_count, entries );
1098 0 : if( key_index == -1 )
1099 0 : return default_value;
1100 : else
1101 0 : return atof(entries[key_index]->value);
1102 : }
1103 :
1104 : /*-----------------------------------------------------------------------------
1105 :
1106 : Name:
1107 : EnvisatFile_SetKeyValueAsDouble()
1108 :
1109 : Purpose:
1110 : Set the value associated with the indicated key as a double.
1111 :
1112 : Description:
1113 : Note that this function attempts to format the new value similarly to
1114 : the previous value. In some cases (expecially exponential values) this
1115 : may not work out well. In case of problems the caller is encourage to
1116 : format the value themselves, and use the EnvisatFile_SetKeyValueAsString
1117 : function, but taking extreme care about the string length.
1118 :
1119 : Inputs:
1120 : self -- the file to be searched.
1121 : mph_or_sph -- Either MPH or SPH depending on the header to be searched.
1122 : key -- the key (name) to be searched for.
1123 : value -- the value to assign.
1124 :
1125 : Outputs:
1126 :
1127 : Returns:
1128 : SUCCESS or FAILURE.
1129 :
1130 : -----------------------------------------------------------------------------*/
1131 :
1132 0 : int EnvisatFile_SetKeyValueAsDouble( EnvisatFile *self,
1133 : EnvisatFile_HeaderFlag mph_or_sph,
1134 : const char *key,
1135 : double value )
1136 :
1137 : {
1138 : char format[32], string_value[128];
1139 : const char *prototype_value;
1140 : int length;
1141 :
1142 0 : prototype_value = EnvisatFile_GetKeyValueAsString( self, mph_or_sph, key, NULL);
1143 0 : if( prototype_value == NULL )
1144 : {
1145 : char error_buf[2048];
1146 :
1147 0 : sprintf( error_buf,
1148 : "Unable to set header field \"%s\", field not found.",
1149 : key );
1150 :
1151 0 : SendError( error_buf );
1152 0 : return FAILURE;
1153 : }
1154 :
1155 0 : length = strlen(prototype_value);
1156 0 : if( prototype_value[length-4] == 'E' )
1157 : {
1158 0 : sprintf( format, "%%+%dE", length-4 );
1159 0 : sprintf( string_value, format, value );
1160 : }
1161 : else
1162 : {
1163 0 : int decimals = 0, i;
1164 0 : for( i = length-1; i > 0; i-- )
1165 : {
1166 0 : if( prototype_value[i] == '.' )
1167 0 : break;
1168 :
1169 0 : decimals++;
1170 : }
1171 :
1172 0 : sprintf( format, "%%+0%d.%df", length, decimals );
1173 0 : sprintf( string_value, format, value );
1174 :
1175 0 : if( (int)strlen(string_value) > length )
1176 0 : string_value[length] = '\0';
1177 : }
1178 :
1179 0 : return EnvisatFile_SetKeyValueAsString( self, mph_or_sph, key, string_value );
1180 : }
1181 :
1182 : /*-----------------------------------------------------------------------------
1183 :
1184 : Name:
1185 : EnvisatFile_GetDatasetIndex()
1186 :
1187 : Purpose:
1188 : Fetch the datasat index give a dataset name.
1189 :
1190 : Description:
1191 : The provided name is extended with spaces, so it isn't necessary for the
1192 : application to pass all the passing spaces.
1193 :
1194 : Inputs:
1195 : self -- the file to be searched.
1196 : ds_name -- the name (DS_NAME) of the dataset to find.
1197 :
1198 : Outputs:
1199 :
1200 : Returns:
1201 : Dataset index that matches, or -1 if none found.
1202 :
1203 : -----------------------------------------------------------------------------*/
1204 :
1205 13 : int EnvisatFile_GetDatasetIndex( EnvisatFile *self, const char *ds_name )
1206 :
1207 : {
1208 : int i;
1209 : char padded_ds_name[100];
1210 :
1211 : /*
1212 : * Padd the name. While the normal product spec says the DS_NAME will
1213 : * be 28 characters, I try to pad more than this incase the specification
1214 : * is changed.
1215 : */
1216 13 : strncpy( padded_ds_name, ds_name, sizeof(padded_ds_name) );
1217 13 : padded_ds_name[sizeof(padded_ds_name)-1] = 0;
1218 1082 : for( i = strlen(padded_ds_name); i < sizeof(padded_ds_name)-1; i++ )
1219 : {
1220 1069 : padded_ds_name[i] = ' ';
1221 : }
1222 13 : padded_ds_name[i] = '\0';
1223 :
1224 : /*
1225 : * Compare only for the full length of DS_NAME we have saved.
1226 : */
1227 75 : for( i = 0; i < self->ds_count; i++ )
1228 : {
1229 75 : if( strncmp( padded_ds_name, self->ds_info[i]->ds_name,
1230 75 : strlen(self->ds_info[i]->ds_name) ) == 0 )
1231 : {
1232 13 : return i;
1233 : }
1234 : }
1235 :
1236 0 : return -1;
1237 : }
1238 :
1239 : /*-----------------------------------------------------------------------------
1240 :
1241 : Name:
1242 : EnvisatFile_GetDatasetInfo()
1243 :
1244 : Purpose:
1245 : Fetch the information associated with a dataset definition.
1246 :
1247 : Description:
1248 : The returned strings are pointers to internal copies, and should not be
1249 : modified, or freed. Note, any of the "output" parameters can safely be
1250 : NULL if it is not needed.
1251 :
1252 : Inputs:
1253 : self -- the file to be searched.
1254 : ds_index -- the dataset index to fetch
1255 :
1256 : Outputs:
1257 : ds_name -- the dataset symbolic name, ie 'MDS1 SQ ADS '.
1258 : ds_type -- the dataset type, ie. 'A', not sure of valid values.
1259 : filename -- dataset filename, normally spaces, or 'NOT USED '.
1260 : ds_offset -- the byte offset in the whole file to the first byte of
1261 : dataset data. This is 0 for unused datasets.
1262 : ds_size -- the size, in bytes, of the whole dataset.
1263 : num_dsr -- the number of records in the dataset.
1264 : dsr_size -- the size of one record in the dataset in bytes, -1 if
1265 : records are variable sized.
1266 :
1267 : Returns:
1268 : SUCCESS if dataset exists, or FAILURE if ds_index is out of range.
1269 :
1270 : -----------------------------------------------------------------------------*/
1271 :
1272 1239 : int EnvisatFile_GetDatasetInfo( EnvisatFile *self,
1273 : int ds_index,
1274 : char **ds_name,
1275 : char **ds_type,
1276 : char **filename,
1277 : int *ds_offset,
1278 : int *ds_size,
1279 : int *num_dsr,
1280 : int *dsr_size )
1281 :
1282 : {
1283 1239 : if( ds_index < 0 || ds_index >= self->ds_count )
1284 39 : return FAILURE;
1285 :
1286 1200 : if( ds_name != NULL )
1287 1080 : *ds_name = self->ds_info[ds_index]->ds_name;
1288 1200 : if( ds_type != NULL )
1289 454 : *ds_type = self->ds_info[ds_index]->ds_type;
1290 1200 : if( filename != NULL )
1291 720 : *filename = self->ds_info[ds_index]->filename;
1292 1200 : if( ds_offset != NULL )
1293 467 : *ds_offset = self->ds_info[ds_index]->ds_offset;
1294 1200 : if( ds_size != NULL )
1295 0 : *ds_size = self->ds_info[ds_index]->ds_size;
1296 1200 : if( num_dsr != NULL )
1297 840 : *num_dsr = self->ds_info[ds_index]->num_dsr;
1298 1200 : if( dsr_size != NULL )
1299 840 : *dsr_size = self->ds_info[ds_index]->dsr_size;
1300 :
1301 1200 : return SUCCESS;
1302 : }
1303 :
1304 : /*-----------------------------------------------------------------------------
1305 :
1306 : Name:
1307 : EnvisatFile_SetDatasetInfo()
1308 :
1309 : Purpose:
1310 : Update the information associated with a dataset definition.
1311 :
1312 : Description:
1313 :
1314 : Inputs:
1315 : self -- the file to be searched.
1316 : ds_index -- the dataset index to fetch
1317 : ds_offset -- the byte offset in the whole file to the first byte of
1318 : dataset data. This is 0 for unused datasets.
1319 : ds_size -- the size, in bytes, of the whole dataset.
1320 : num_dsr -- the number of records in the dataset.
1321 : dsr_size -- the size of one record in the dataset in bytes, -1 if
1322 : records are variable sized.
1323 :
1324 : Outputs:
1325 :
1326 : Returns:
1327 : SUCCESS or FAILURE.
1328 :
1329 : -----------------------------------------------------------------------------*/
1330 :
1331 0 : int EnvisatFile_SetDatasetInfo( EnvisatFile *self,
1332 : int ds_index,
1333 : int ds_offset,
1334 : int ds_size,
1335 : int num_dsr,
1336 : int dsr_size )
1337 :
1338 : {
1339 0 : if( ds_index < 0 || ds_index >= self->ds_count )
1340 0 : return FAILURE;
1341 :
1342 0 : self->ds_info[ds_index]->ds_offset = ds_offset;
1343 0 : self->ds_info[ds_index]->ds_size = ds_size;
1344 0 : self->ds_info[ds_index]->num_dsr = num_dsr;
1345 0 : self->ds_info[ds_index]->dsr_size = dsr_size;
1346 0 : self->header_dirty = 1;
1347 :
1348 0 : return SUCCESS;
1349 : }
1350 :
1351 :
1352 : /*-----------------------------------------------------------------------------
1353 :
1354 : Name:
1355 : EnvisatFile_ReadDatasetChunk()
1356 :
1357 : Purpose:
1358 : Read an arbitrary chunk of a dataset.
1359 :
1360 : Description:
1361 : Note that no range checking is made on offset and size, and data may be
1362 : read from outside the dataset if they are inappropriate.
1363 :
1364 : Inputs:
1365 : self -- the file to be searched.
1366 : ds_index -- the index of dataset to access.
1367 : offset -- byte offset within database to read.
1368 : size -- size of buffer to fill in bytes.
1369 : buffer -- buffer to load data into
1370 :
1371 : Outputs:
1372 : buffer is updated on SUCCESS.
1373 :
1374 : Returns:
1375 : SUCCESS or FAILURE
1376 :
1377 : -----------------------------------------------------------------------------*/
1378 :
1379 0 : int EnvisatFile_ReadDatasetChunk( EnvisatFile *self,
1380 : int ds_index,
1381 : int offset,
1382 : int size,
1383 : void * buffer )
1384 :
1385 : {
1386 0 : if( ds_index < 0 || ds_index >= self->ds_count )
1387 : {
1388 0 : SendError( "Attempt to read non-existant dataset in "
1389 : "EnvisatFile_ReadDatasetChunk()" );
1390 0 : return FAILURE;
1391 : }
1392 :
1393 0 : if( offset < 0
1394 0 : || offset + size > self->ds_info[ds_index]->ds_size )
1395 : {
1396 0 : SendError( "Attempt to read beyond end of dataset in "
1397 : "EnvisatFile_ReadDatasetChunk()" );
1398 0 : return FAILURE;
1399 : }
1400 :
1401 0 : if( fseek( self->fp, self->ds_info[ds_index]->ds_offset+offset, SEEK_SET )
1402 : != 0 )
1403 : {
1404 0 : SendError( "seek failed in EnvisatFile_ReadChunk()" );
1405 0 : return FAILURE;
1406 : }
1407 :
1408 0 : if( (int) fread( buffer, 1, size, self->fp ) != size )
1409 : {
1410 0 : SendError( "read failed in EnvisatFile_ReadChunk()" );
1411 0 : return FAILURE;
1412 : }
1413 :
1414 0 : return SUCCESS;
1415 : }
1416 :
1417 : /*-----------------------------------------------------------------------------
1418 :
1419 : Name:
1420 : EnvisatFile_WriteDatasetRecord()
1421 :
1422 : Purpose:
1423 : Write an arbitrary dataset record.
1424 :
1425 : Description:
1426 : Note that no range checking is made on offset and size, and data may be
1427 : read from outside the dataset if they are inappropriate.
1428 :
1429 : Inputs:
1430 : self -- the file to be searched.
1431 : ds_index -- the index of dataset to access.
1432 : record_index -- the record to write.
1433 : record_buffer -- buffer to load data into
1434 :
1435 : Outputs:
1436 :
1437 : Returns:
1438 : SUCCESS or FAILURE
1439 :
1440 : -----------------------------------------------------------------------------*/
1441 :
1442 0 : int EnvisatFile_WriteDatasetRecord( EnvisatFile *self,
1443 : int ds_index,
1444 : int record_index,
1445 : void *buffer )
1446 :
1447 : {
1448 : int absolute_offset;
1449 : int result;
1450 :
1451 0 : if( ds_index < 0 || ds_index >= self->ds_count )
1452 : {
1453 0 : SendError( "Attempt to write non-existant dataset in "
1454 : "EnvisatFile_WriteDatasetRecord()" );
1455 0 : return FAILURE;
1456 : }
1457 :
1458 0 : if( record_index < 0
1459 0 : || record_index >= self->ds_info[ds_index]->num_dsr )
1460 : {
1461 0 : SendError( "Attempt to write beyond end of dataset in "
1462 : "EnvisatFile_WriteDatasetRecord()" );
1463 0 : return FAILURE;
1464 : }
1465 :
1466 0 : absolute_offset = self->ds_info[ds_index]->ds_offset
1467 0 : + record_index * self->ds_info[ds_index]->dsr_size;
1468 :
1469 0 : if( fseek( self->fp, absolute_offset, SEEK_SET ) != 0 )
1470 : {
1471 0 : SendError( "seek failed in EnvisatFile_WriteDatasetRecord()" );
1472 0 : return FAILURE;
1473 : }
1474 :
1475 0 : result = fwrite( buffer, 1, self->ds_info[ds_index]->dsr_size, self->fp );
1476 0 : if( result != self->ds_info[ds_index]->dsr_size )
1477 : {
1478 0 : SendError( "write failed in EnvisatFile_WriteDatasetRecord()" );
1479 0 : return FAILURE;
1480 : }
1481 :
1482 0 : return SUCCESS;
1483 : }
1484 :
1485 : /*-----------------------------------------------------------------------------
1486 :
1487 : Name:
1488 : EnvisatFile_ReadDatasetRecord()
1489 :
1490 : Purpose:
1491 : Read an arbitrary dataset record.
1492 :
1493 : Description:
1494 : Note that no range checking is made on offset and size, and data may be
1495 : read from outside the dataset if they are inappropriate.
1496 :
1497 : Inputs:
1498 : self -- the file to be searched.
1499 : ds_index -- the index of dataset to access.
1500 : record_index -- the record to write.
1501 : record_buffer -- buffer to load data into
1502 :
1503 : Outputs:
1504 :
1505 : Returns:
1506 : SUCCESS or FAILURE
1507 :
1508 : -----------------------------------------------------------------------------*/
1509 :
1510 622 : int EnvisatFile_ReadDatasetRecord( EnvisatFile *self,
1511 : int ds_index,
1512 : int record_index,
1513 : void *buffer )
1514 :
1515 : {
1516 : int absolute_offset;
1517 : int result;
1518 :
1519 622 : if( ds_index < 0 || ds_index >= self->ds_count )
1520 : {
1521 0 : SendError( "Attempt to write non-existant dataset in "
1522 : "EnvisatFile_WriteDatasetRecord()" );
1523 0 : return FAILURE;
1524 : }
1525 :
1526 1244 : if( record_index < 0
1527 622 : || record_index >= self->ds_info[ds_index]->num_dsr )
1528 : {
1529 0 : SendError( "Attempt to write beyond end of dataset in "
1530 : "EnvisatFile_WriteDatasetRecord()" );
1531 0 : return FAILURE;
1532 : }
1533 :
1534 1244 : absolute_offset = self->ds_info[ds_index]->ds_offset
1535 622 : + record_index * self->ds_info[ds_index]->dsr_size;
1536 :
1537 622 : if( fseek( self->fp, absolute_offset, SEEK_SET ) != 0 )
1538 : {
1539 0 : SendError( "seek failed in EnvisatFile_WriteDatasetRecord()" );
1540 0 : return FAILURE;
1541 : }
1542 :
1543 622 : result = fread( buffer, 1, self->ds_info[ds_index]->dsr_size, self->fp );
1544 622 : if( result != self->ds_info[ds_index]->dsr_size )
1545 : {
1546 0 : SendError( "read failed in EnvisatFile_ReadDatasetRecord()" );
1547 0 : return FAILURE;
1548 : }
1549 :
1550 622 : return SUCCESS;
1551 : }
1552 :
1553 : /*-----------------------------------------------------------------------------
1554 :
1555 : Name:
1556 : S_NameValueList_FindKey()
1557 :
1558 : Purpose:
1559 : Search for given key in list of name/value pairs.
1560 :
1561 : Description:
1562 : Scans list looking for index of EnvisatNameValue where the key matches
1563 : (case sensitive) the passed in name.
1564 :
1565 : Inputs:
1566 : key -- the key, such as "SLICE_POSITION" being searched for.
1567 : entry_count -- the number of items in the entries array.
1568 : entries -- array of name/value structures to search.
1569 :
1570 : Outputs:
1571 :
1572 : Returns:
1573 : array index into entries, or -1 on failure.
1574 :
1575 : -----------------------------------------------------------------------------*/
1576 :
1577 3551 : int S_NameValueList_FindKey( const char *key,
1578 : int entry_count,
1579 : EnvisatNameValue **entries )
1580 :
1581 : {
1582 : int i;
1583 :
1584 27007 : for( i = 0; i < entry_count; i++ )
1585 : {
1586 26111 : if( strcmp(entries[i]->key,key) == 0 )
1587 2655 : return i;
1588 : }
1589 :
1590 896 : return -1;
1591 : }
1592 :
1593 : /*-----------------------------------------------------------------------------
1594 :
1595 : Name:
1596 : S_NameValueList_FindValue()
1597 :
1598 : Purpose:
1599 : Search for given key in list of name/value pairs, and return value.
1600 :
1601 : Description:
1602 : Returns value string or default if key not found.
1603 :
1604 : Inputs:
1605 : key -- the key, such as "SLICE_POSITION" being searched for.
1606 : entry_count -- the number of items in the entries array.
1607 : entries -- array of name/value structures to search.
1608 : default_value -- value to use if key not found.
1609 :
1610 : Outputs:
1611 :
1612 : Returns:
1613 : value string, or default if key not found.
1614 :
1615 : -----------------------------------------------------------------------------*/
1616 :
1617 2520 : const char *S_NameValueList_FindValue( const char *key,
1618 : int entry_count,
1619 : EnvisatNameValue **entries,
1620 : const char *default_value )
1621 :
1622 : {
1623 : int i;
1624 :
1625 2520 : i = S_NameValueList_FindKey( key, entry_count, entries );
1626 2520 : if( i == -1 )
1627 882 : return default_value;
1628 : else
1629 1638 : return entries[i]->value;
1630 : }
1631 :
1632 : /*-----------------------------------------------------------------------------
1633 :
1634 : Name:
1635 : S_NameValueList_Parse()
1636 :
1637 : Purpose:
1638 : Parse a block of envisat style name/value pairs into an
1639 : EnvisatNameValue structure list.
1640 :
1641 : Description:
1642 : The passed in text block should be zero terminated. The entry_count,
1643 : and entries should be pre-initialized (normally to 0 and NULL).
1644 :
1645 : Inputs:
1646 : text -- the block of text, multiple lines, to be processed.
1647 :
1648 : Outputs:
1649 : entry_count -- returns with the updated number of entries in the
1650 : entries array.
1651 : entries -- returns with updated array info structures.
1652 :
1653 : Returns:
1654 : SUCCESS or FAILURE
1655 :
1656 : -----------------------------------------------------------------------------*/
1657 :
1658 386 : int S_NameValueList_Parse( const char *text, int text_offset,
1659 : int *entry_count,
1660 : EnvisatNameValue ***entries )
1661 :
1662 : {
1663 386 : const char *next_text = text;
1664 :
1665 : /*
1666 : * Loop over each input line in the text block.
1667 : */
1668 3794 : while( *next_text != '\0' )
1669 : {
1670 : char line[1024];
1671 3022 : int line_len = 0, equal_index, src_char, line_offset;
1672 : EnvisatNameValue *entry;
1673 :
1674 : /*
1675 : * Extract one line of text into the "line" buffer, and remove the
1676 : * newline character. Eat leading spaces.
1677 : */
1678 53887 : while( *next_text == ' ' )
1679 : {
1680 47843 : next_text++;
1681 : }
1682 3022 : line_offset = (int) (next_text - text) + text_offset;
1683 89338 : while( *next_text != '\0' && *next_text != '\n' )
1684 : {
1685 83294 : if( line_len > sizeof(line)-1 )
1686 : {
1687 0 : SendError( "S_NameValueList_Parse(): "
1688 : "Corrupt line, longer than 1024 characters." );
1689 0 : return FAILURE;
1690 : }
1691 :
1692 83294 : line[line_len++] = *(next_text++);
1693 : }
1694 :
1695 3022 : line[line_len] = '\0';
1696 3022 : if( *next_text == '\n' )
1697 2649 : next_text++;
1698 :
1699 : /*
1700 : * Blank lines are permitted. We will skip processing of any line
1701 : * that doesn't have an equal sign, under the assumption it is
1702 : * white space.
1703 : */
1704 3022 : if( strstr( line, "=") == NULL )
1705 484 : continue;
1706 :
1707 : /*
1708 : * Create the name/value info structure.
1709 : */
1710 2538 : entry = (EnvisatNameValue *) calloc(sizeof(EnvisatNameValue),1);
1711 2538 : entry->literal_line = strdup(line);
1712 :
1713 : /*
1714 : * Capture the key. We take everything up to the equal sign. There
1715 : * shouldn't be any white space, but if so, we take it as part of the
1716 : * key.
1717 : */
1718 2538 : equal_index = strstr(line, "=") - line;
1719 2538 : entry->key = (char *) malloc(equal_index+1);
1720 2538 : strncpy( entry->key, line, equal_index );
1721 2538 : entry->key[equal_index] = '\0';
1722 2538 : entry->value_offset = line_offset + equal_index + 1;
1723 :
1724 : /*
1725 : * If the next character after the equal sign is a double quote, then
1726 : * the value is a string. Suck out the text between the double quotes.
1727 : */
1728 2538 : if( line[equal_index+1] == '"' )
1729 : {
1730 54427 : for( src_char = equal_index + 2;
1731 53716 : line[src_char] != '\0' && line[src_char] != '"';
1732 26147 : src_char++ ) {}
1733 :
1734 711 : line[src_char] = '\0';
1735 711 : entry->value = strdup( line + equal_index + 2 );
1736 711 : entry->value_offset += 1;
1737 : }
1738 :
1739 : /*
1740 : * The value is numeric, and may include a units field.
1741 : */
1742 : else
1743 : {
1744 72241 : for( src_char = equal_index + 1;
1745 47912 : line[src_char] != '\0' && line[src_char] != '<'
1746 46085 : && line[src_char] != ' ';
1747 22502 : src_char++ ) {}
1748 :
1749 : /* capture units */
1750 1827 : if( line[src_char] == '<' )
1751 : {
1752 : int dst_char;
1753 :
1754 13054 : for( dst_char = src_char+1;
1755 11973 : line[dst_char] != '>' && line[dst_char] != '\0';
1756 5446 : dst_char++ ) {}
1757 :
1758 1081 : line[dst_char] = '\0';
1759 1081 : entry->units = strdup( line + src_char + 1 );
1760 : }
1761 :
1762 1827 : line[src_char] = '\0';
1763 1827 : entry->value = strdup( line + equal_index + 1 );
1764 : }
1765 :
1766 : /*
1767 : * Add the entry to the name/value list.
1768 : */
1769 2538 : (*entry_count)++;
1770 5076 : *entries = (EnvisatNameValue **)
1771 5076 : realloc( *entries, *entry_count * sizeof(EnvisatNameValue*) );
1772 :
1773 2538 : if( *entries == NULL )
1774 : {
1775 0 : *entry_count = 0;
1776 0 : return FAILURE;
1777 : }
1778 :
1779 2538 : (*entries)[*entry_count-1] = entry;
1780 : }
1781 :
1782 386 : return SUCCESS;
1783 : }
1784 :
1785 : /*-----------------------------------------------------------------------------
1786 :
1787 : Name:
1788 : S_NameValueList_Rewrite()
1789 :
1790 : Purpose:
1791 : Rewrite the values of a name/value list in the file.
1792 :
1793 : Description:
1794 :
1795 : Inputs:
1796 : fp -- the FILE to operate on.
1797 : entry_count -- number of entries to write.
1798 : entries -- array of entry descriptions.
1799 :
1800 : Returns:
1801 : SUCCESS or FAILURE
1802 :
1803 :
1804 : -----------------------------------------------------------------------------*/
1805 :
1806 0 : int S_NameValueList_Rewrite( FILE * fp, int entry_count,
1807 : EnvisatNameValue **entries )
1808 :
1809 : {
1810 : int i;
1811 :
1812 0 : for( i = 0; i < entry_count; i++ )
1813 : {
1814 0 : EnvisatNameValue *entry = entries[i];
1815 :
1816 0 : if( fseek( fp, entry->value_offset, SEEK_SET ) != 0 )
1817 : {
1818 0 : SendError( "fseek() failed writing name/value list." );
1819 0 : return FAILURE;
1820 : }
1821 :
1822 0 : if( fwrite( entry->value, 1, strlen(entry->value), fp ) !=
1823 0 : strlen(entry->value) )
1824 : {
1825 0 : SendError( "fwrite() failed writing name/value list." );
1826 0 : return FAILURE;
1827 : }
1828 : }
1829 :
1830 0 : return SUCCESS;
1831 : }
1832 :
1833 :
1834 : /*-----------------------------------------------------------------------------
1835 :
1836 : Name:
1837 : S_NameValueList_Destroy()
1838 :
1839 : Purpose:
1840 : Free resources associated with a name/value list.
1841 :
1842 : Description:
1843 : The count, and name/value list pointers are set to 0/NULL on completion.
1844 :
1845 : Inputs:
1846 : entry_count -- returns with the updated number of entries in the
1847 : entries array.
1848 : entries -- returns with updated array info structures.
1849 :
1850 : Outputs:
1851 : entry_count -- Set to zero.
1852 : entries -- Sett o NULL.
1853 :
1854 : Returns:
1855 :
1856 :
1857 : -----------------------------------------------------------------------------*/
1858 :
1859 386 : void S_NameValueList_Destroy( int *entry_count,
1860 : EnvisatNameValue ***entries )
1861 :
1862 : {
1863 : int i;
1864 :
1865 2924 : for( i = 0; i < *entry_count; i++ )
1866 : {
1867 2538 : free( (*entries)[i]->key );
1868 2538 : free( (*entries)[i]->value );
1869 2538 : free( (*entries)[i]->units );
1870 2538 : free( (*entries)[i]->literal_line );
1871 2538 : free( (*entries)[i] );
1872 : }
1873 :
1874 386 : free( *entries );
1875 :
1876 386 : *entry_count = 0;
1877 386 : *entries = NULL;
1878 386 : }
1879 :
1880 : /* EOF */
1881 :
|