1 : /******************************************************************************
2 : * $Id: EnvisatFile.c 11332 2007-04-21 20:48:53Z warmerdam $
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 11332 2007-04-21 20:48:53Z warmerdam $");
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 : static int EnvisatFile_SetupLevel0( EnvisatFile *self )
138 :
139 0 : {
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 : 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 : || 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 : int EnvisatFile_Open( EnvisatFile **self_ptr,
214 : const char *filename,
215 : const char *mode )
216 :
217 0 : {
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 0 : *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 0 : if( strcmp(mode,"r") == 0 )
231 0 : 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 0 : fp = fopen( filename, mode );
246 :
247 0 : 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 0 : self = (EnvisatFile *) calloc(sizeof(EnvisatFile),1);
263 0 : if( self == NULL )
264 0 : return FAILURE;
265 :
266 0 : self->fp = fp;
267 0 : self->filename = strdup( filename );
268 0 : self->header_dirty = 0;
269 0 : 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 0 : 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 0 : mph_data[MPH_SIZE] = '\0';
283 0 : 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 0 : if( EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", -1 ) == 0
292 : && strncmp(EnvisatFile_GetKeyValueAsString( self, MPH, "PRODUCT", ""),
293 : "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 0 : sph_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", 0 );
312 :
313 0 : 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 0 : sph_data = (char *) malloc(sph_size + 1 );
321 0 : if( sph_data == NULL )
322 0 : return FAILURE;
323 :
324 0 : 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 0 : sph_data[sph_size] = '\0';
332 0 : ds_data = strstr(sph_data,"DS_NAME");
333 0 : if( ds_data != NULL )
334 : {
335 0 : self->dsd_offset = (int) (ds_data - sph_data) + MPH_SIZE;
336 0 : *(ds_data-1) = '\0';
337 : }
338 :
339 0 : 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 0 : num_dsd = EnvisatFile_GetKeyValueAsInt( self, MPH, "NUM_DSD", 0 );
348 0 : dsd_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "DSD_SIZE", 0 );
349 :
350 0 : 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 0 : self->ds_info = (EnvisatDatasetInfo **)
357 : calloc(sizeof(EnvisatDatasetInfo*),num_dsd);
358 0 : if( self->ds_info == NULL )
359 0 : return FAILURE;
360 :
361 0 : for( i = 0; i < num_dsd; i++ )
362 : {
363 0 : int dsdh_count = 0;
364 0 : 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 0 : dsd_data = ds_data + i * dsd_size;
372 0 : dsd_data[dsd_size-1] = '\0';
373 :
374 0 : 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 0 : ds_info = (EnvisatDatasetInfo *) calloc(sizeof(EnvisatDatasetInfo),1);
382 :
383 0 : ds_info->ds_name = strdup(
384 : S_NameValueList_FindValue( "DS_NAME",
385 : dsdh_count, dsdh_entries, "" ));
386 0 : ds_info->ds_type = strdup(
387 : S_NameValueList_FindValue( "DS_TYPE",
388 : dsdh_count, dsdh_entries, "" ));
389 0 : ds_info->filename = strdup(
390 : S_NameValueList_FindValue( "FILENAME",
391 : dsdh_count, dsdh_entries, "" ));
392 0 : ds_info->ds_offset = atoi(
393 : S_NameValueList_FindValue( "DS_OFFSET",
394 : dsdh_count, dsdh_entries, "0" ));
395 0 : ds_info->ds_size = atoi(
396 : S_NameValueList_FindValue( "DS_SIZE",
397 : dsdh_count, dsdh_entries, "0" ));
398 0 : ds_info->num_dsr = atoi(
399 : S_NameValueList_FindValue( "NUM_DSR",
400 : dsdh_count, dsdh_entries, "0" ));
401 0 : ds_info->dsr_size = atoi(
402 : S_NameValueList_FindValue( "DSR_SIZE",
403 : dsdh_count, dsdh_entries, "0" ));
404 :
405 0 : S_NameValueList_Destroy( &dsdh_count, &dsdh_entries );
406 :
407 0 : self->ds_info[i] = ds_info;
408 0 : self->ds_count++;
409 : }
410 :
411 0 : free( sph_data );
412 :
413 : /*
414 : * Return successfully.
415 : */
416 0 : *self_ptr = self;
417 :
418 0 : 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 : int EnvisatFile_Create( EnvisatFile **self_ptr,
444 : const char *filename,
445 : const char *template_file )
446 :
447 0 : {
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 : int EnvisatFile_GetCurrentLength( EnvisatFile *self )
531 :
532 0 : {
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 : static int EnvisatFile_RewriteHeader( EnvisatFile *self )
575 :
576 0 : {
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 : 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 : 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 : 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 : 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 : void EnvisatFile_Close( EnvisatFile *self )
680 :
681 0 : {
682 : int i;
683 :
684 : /*
685 : * Do we need to write out the header information?
686 : */
687 0 : if( self->header_dirty )
688 0 : EnvisatFile_RewriteHeader( self );
689 :
690 : /*
691 : * Close file.
692 : */
693 0 : if( self->fp != NULL )
694 0 : fclose( self->fp );
695 :
696 : /*
697 : * Clean up data structures.
698 : */
699 0 : S_NameValueList_Destroy( &(self->mph_count), &(self->mph_entries) );
700 0 : S_NameValueList_Destroy( &(self->sph_count), &(self->sph_entries) );
701 :
702 0 : for( i = 0; i < self->ds_count; i++ )
703 : {
704 0 : if( self->ds_info != NULL && self->ds_info[i] != NULL )
705 : {
706 0 : free( self->ds_info[i]->ds_name );
707 0 : free( self->ds_info[i]->ds_type );
708 0 : free( self->ds_info[i]->filename );
709 0 : free( self->ds_info[i] );
710 : }
711 : }
712 0 : if( self->ds_info != NULL )
713 0 : free( self->ds_info );
714 0 : if( self->filename != NULL )
715 0 : free( self->filename );
716 :
717 0 : free( self );
718 0 : }
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 : const char *EnvisatFile_GetFilename( EnvisatFile *self )
742 :
743 0 : {
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 : const char *EnvisatFile_GetKeyByIndex( EnvisatFile *self,
773 : EnvisatFile_HeaderFlag mph_or_sph,
774 : int key_index )
775 :
776 0 : {
777 : int entry_count;
778 : EnvisatNameValue **entries;
779 :
780 : /*
781 : * Select source list.
782 : */
783 0 : if( mph_or_sph == MPH )
784 : {
785 0 : entry_count = self->mph_count;
786 0 : entries = self->mph_entries;
787 : }
788 : else
789 : {
790 0 : entry_count = self->sph_count;
791 0 : entries = self->sph_entries;
792 : }
793 :
794 0 : if( key_index < 0 || key_index >= entry_count )
795 0 : return NULL;
796 : else
797 0 : 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 : const char *EnvisatFile_GetKeyValueAsString( EnvisatFile *self,
824 : EnvisatFile_HeaderFlag mph_or_sph,
825 : const char *key,
826 : const char *default_value )
827 :
828 0 : {
829 : int entry_count, key_index;
830 : EnvisatNameValue **entries;
831 :
832 : /*
833 : * Select source list.
834 : */
835 0 : if( mph_or_sph == MPH )
836 : {
837 0 : entry_count = self->mph_count;
838 0 : entries = self->mph_entries;
839 : }
840 : else
841 : {
842 0 : entry_count = self->sph_count;
843 0 : entries = self->sph_entries;
844 : }
845 :
846 : /*
847 : * Find and return the value.
848 : */
849 0 : key_index = S_NameValueList_FindKey( key, entry_count, entries );
850 0 : if( key_index == -1 )
851 0 : return default_value;
852 : else
853 0 : 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 : int EnvisatFile_SetKeyValueAsString( EnvisatFile *self,
880 : EnvisatFile_HeaderFlag mph_or_sph,
881 : const char *key,
882 : const char *value )
883 :
884 0 : {
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 : strlen(entries[key_index]->value) );
929 : }
930 : else
931 : {
932 0 : memset( entries[key_index]->value, ' ',
933 : 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 : int EnvisatFile_GetKeyValueAsInt( EnvisatFile *self,
964 : EnvisatFile_HeaderFlag mph_or_sph,
965 : const char *key,
966 : int default_value )
967 :
968 0 : {
969 : int entry_count, key_index;
970 : EnvisatNameValue **entries;
971 :
972 : /*
973 : * Select source list.
974 : */
975 0 : if( mph_or_sph == MPH )
976 : {
977 0 : entry_count = self->mph_count;
978 0 : entries = self->mph_entries;
979 : }
980 : else
981 : {
982 0 : entry_count = self->sph_count;
983 0 : entries = self->sph_entries;
984 : }
985 :
986 : /*
987 : * Find and return the value.
988 : */
989 0 : key_index = S_NameValueList_FindKey( key, entry_count, entries );
990 0 : if( key_index == -1 )
991 0 : return default_value;
992 : else
993 0 : 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 : int EnvisatFile_SetKeyValueAsInt( EnvisatFile *self,
1020 : EnvisatFile_HeaderFlag mph_or_sph,
1021 : const char *key,
1022 : int value )
1023 :
1024 0 : {
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 : double EnvisatFile_GetKeyValueAsDouble( EnvisatFile *self,
1072 : EnvisatFile_HeaderFlag mph_or_sph,
1073 : const char *key,
1074 : double default_value )
1075 :
1076 0 : {
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 : int EnvisatFile_SetKeyValueAsDouble( EnvisatFile *self,
1133 : EnvisatFile_HeaderFlag mph_or_sph,
1134 : const char *key,
1135 : double value )
1136 :
1137 0 : {
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 : int EnvisatFile_GetDatasetIndex( EnvisatFile *self, const char *ds_name )
1206 :
1207 0 : {
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 0 : strcpy( padded_ds_name, ds_name );
1217 0 : for( i = strlen(padded_ds_name); i < sizeof(padded_ds_name)-1; i++ )
1218 : {
1219 0 : padded_ds_name[i] = ' ';
1220 : }
1221 0 : padded_ds_name[i] = '\0';
1222 :
1223 : /*
1224 : * Compare only for the full length of DS_NAME we have saved.
1225 : */
1226 0 : for( i = 0; i < self->ds_count; i++ )
1227 : {
1228 0 : if( strncmp( padded_ds_name, self->ds_info[i]->ds_name,
1229 : strlen(self->ds_info[i]->ds_name) ) == 0 )
1230 : {
1231 0 : return i;
1232 : }
1233 : }
1234 :
1235 0 : return -1;
1236 : }
1237 :
1238 : /*-----------------------------------------------------------------------------
1239 :
1240 : Name:
1241 : EnvisatFile_GetDatasetInfo()
1242 :
1243 : Purpose:
1244 : Fetch the information associated with a dataset definition.
1245 :
1246 : Description:
1247 : The returned strings are pointers to internal copies, and should not be
1248 : modified, or freed. Note, any of the "output" parameters can safely be
1249 : NULL if it is not needed.
1250 :
1251 : Inputs:
1252 : self -- the file to be searched.
1253 : ds_index -- the dataset index to fetch
1254 :
1255 : Outputs:
1256 : ds_name -- the dataset symbolic name, ie 'MDS1 SQ ADS '.
1257 : ds_type -- the dataset type, ie. 'A', not sure of valid values.
1258 : filename -- dataset filename, normally spaces, or 'NOT USED '.
1259 : ds_offset -- the byte offset in the whole file to the first byte of
1260 : dataset data. This is 0 for unused datasets.
1261 : ds_size -- the size, in bytes, of the whole dataset.
1262 : num_dsr -- the number of records in the dataset.
1263 : dsr_size -- the size of one record in the dataset in bytes, -1 if
1264 : records are variable sized.
1265 :
1266 : Returns:
1267 : SUCCESS if dataset exists, or FAILURE if ds_index is out of range.
1268 :
1269 : -----------------------------------------------------------------------------*/
1270 :
1271 : int EnvisatFile_GetDatasetInfo( EnvisatFile *self,
1272 : int ds_index,
1273 : char **ds_name,
1274 : char **ds_type,
1275 : char **filename,
1276 : int *ds_offset,
1277 : int *ds_size,
1278 : int *num_dsr,
1279 : int *dsr_size )
1280 :
1281 0 : {
1282 0 : if( ds_index < 0 || ds_index >= self->ds_count )
1283 0 : return FAILURE;
1284 :
1285 0 : if( ds_name != NULL )
1286 0 : *ds_name = self->ds_info[ds_index]->ds_name;
1287 0 : if( ds_type != NULL )
1288 0 : *ds_type = self->ds_info[ds_index]->ds_type;
1289 0 : if( filename != NULL )
1290 0 : *filename = self->ds_info[ds_index]->filename;
1291 0 : if( ds_offset != NULL )
1292 0 : *ds_offset = self->ds_info[ds_index]->ds_offset;
1293 0 : if( ds_size != NULL )
1294 0 : *ds_size = self->ds_info[ds_index]->ds_size;
1295 0 : if( num_dsr != NULL )
1296 0 : *num_dsr = self->ds_info[ds_index]->num_dsr;
1297 0 : if( dsr_size != NULL )
1298 0 : *dsr_size = self->ds_info[ds_index]->dsr_size;
1299 :
1300 0 : return SUCCESS;
1301 : }
1302 :
1303 : /*-----------------------------------------------------------------------------
1304 :
1305 : Name:
1306 : EnvisatFile_SetDatasetInfo()
1307 :
1308 : Purpose:
1309 : Update the information associated with a dataset definition.
1310 :
1311 : Description:
1312 :
1313 : Inputs:
1314 : self -- the file to be searched.
1315 : ds_index -- the dataset index to fetch
1316 : ds_offset -- the byte offset in the whole file to the first byte of
1317 : dataset data. This is 0 for unused datasets.
1318 : ds_size -- the size, in bytes, of the whole dataset.
1319 : num_dsr -- the number of records in the dataset.
1320 : dsr_size -- the size of one record in the dataset in bytes, -1 if
1321 : records are variable sized.
1322 :
1323 : Outputs:
1324 :
1325 : Returns:
1326 : SUCCESS or FAILURE.
1327 :
1328 : -----------------------------------------------------------------------------*/
1329 :
1330 : int EnvisatFile_SetDatasetInfo( EnvisatFile *self,
1331 : int ds_index,
1332 : int ds_offset,
1333 : int ds_size,
1334 : int num_dsr,
1335 : int dsr_size )
1336 :
1337 0 : {
1338 0 : if( ds_index < 0 || ds_index >= self->ds_count )
1339 0 : return FAILURE;
1340 :
1341 0 : self->ds_info[ds_index]->ds_offset = ds_offset;
1342 0 : self->ds_info[ds_index]->ds_size = ds_size;
1343 0 : self->ds_info[ds_index]->num_dsr = num_dsr;
1344 0 : self->ds_info[ds_index]->dsr_size = dsr_size;
1345 0 : self->header_dirty = 1;
1346 :
1347 0 : return SUCCESS;
1348 : }
1349 :
1350 :
1351 : /*-----------------------------------------------------------------------------
1352 :
1353 : Name:
1354 : EnvisatFile_ReadDatasetChunk()
1355 :
1356 : Purpose:
1357 : Read an arbitrary chunk of a dataset.
1358 :
1359 : Description:
1360 : Note that no range checking is made on offset and size, and data may be
1361 : read from outside the dataset if they are inappropriate.
1362 :
1363 : Inputs:
1364 : self -- the file to be searched.
1365 : ds_index -- the index of dataset to access.
1366 : offset -- byte offset within database to read.
1367 : size -- size of buffer to fill in bytes.
1368 : buffer -- buffer to load data into
1369 :
1370 : Outputs:
1371 : buffer is updated on SUCCESS.
1372 :
1373 : Returns:
1374 : SUCCESS or FAILURE
1375 :
1376 : -----------------------------------------------------------------------------*/
1377 :
1378 : int EnvisatFile_ReadDatasetChunk( EnvisatFile *self,
1379 : int ds_index,
1380 : int offset,
1381 : int size,
1382 : void * buffer )
1383 :
1384 0 : {
1385 0 : if( ds_index < 0 || ds_index >= self->ds_count )
1386 : {
1387 0 : SendError( "Attempt to read non-existant dataset in "
1388 : "EnvisatFile_ReadDatasetChunk()" );
1389 0 : return FAILURE;
1390 : }
1391 :
1392 0 : if( offset < 0
1393 : || offset + size > self->ds_info[ds_index]->ds_size )
1394 : {
1395 0 : SendError( "Attempt to read beyond end of dataset in "
1396 : "EnvisatFile_ReadDatasetChunk()" );
1397 0 : return FAILURE;
1398 : }
1399 :
1400 0 : if( fseek( self->fp, self->ds_info[ds_index]->ds_offset+offset, SEEK_SET )
1401 : != 0 )
1402 : {
1403 0 : SendError( "seek failed in EnvisatFile_ReadChunk()" );
1404 0 : return FAILURE;
1405 : }
1406 :
1407 0 : if( (int) fread( buffer, 1, size, self->fp ) != size )
1408 : {
1409 0 : SendError( "read failed in EnvisatFile_ReadChunk()" );
1410 0 : return FAILURE;
1411 : }
1412 :
1413 0 : return SUCCESS;
1414 : }
1415 :
1416 : /*-----------------------------------------------------------------------------
1417 :
1418 : Name:
1419 : EnvisatFile_WriteDatasetRecord()
1420 :
1421 : Purpose:
1422 : Write an arbitrary dataset record.
1423 :
1424 : Description:
1425 : Note that no range checking is made on offset and size, and data may be
1426 : read from outside the dataset if they are inappropriate.
1427 :
1428 : Inputs:
1429 : self -- the file to be searched.
1430 : ds_index -- the index of dataset to access.
1431 : record_index -- the record to write.
1432 : record_buffer -- buffer to load data into
1433 :
1434 : Outputs:
1435 :
1436 : Returns:
1437 : SUCCESS or FAILURE
1438 :
1439 : -----------------------------------------------------------------------------*/
1440 :
1441 : int EnvisatFile_WriteDatasetRecord( EnvisatFile *self,
1442 : int ds_index,
1443 : int record_index,
1444 : void *buffer )
1445 :
1446 0 : {
1447 : int absolute_offset;
1448 : int result;
1449 :
1450 0 : if( ds_index < 0 || ds_index >= self->ds_count )
1451 : {
1452 0 : SendError( "Attempt to write non-existant dataset in "
1453 : "EnvisatFile_WriteDatasetRecord()" );
1454 0 : return FAILURE;
1455 : }
1456 :
1457 0 : if( record_index < 0
1458 : || record_index >= self->ds_info[ds_index]->num_dsr )
1459 : {
1460 0 : SendError( "Attempt to write beyond end of dataset in "
1461 : "EnvisatFile_WriteDatasetRecord()" );
1462 0 : return FAILURE;
1463 : }
1464 :
1465 0 : absolute_offset = self->ds_info[ds_index]->ds_offset
1466 : + record_index * self->ds_info[ds_index]->dsr_size;
1467 :
1468 0 : if( fseek( self->fp, absolute_offset, SEEK_SET ) != 0 )
1469 : {
1470 0 : SendError( "seek failed in EnvisatFile_WriteDatasetRecord()" );
1471 0 : return FAILURE;
1472 : }
1473 :
1474 0 : result = fwrite( buffer, 1, self->ds_info[ds_index]->dsr_size, self->fp );
1475 0 : if( result != self->ds_info[ds_index]->dsr_size )
1476 : {
1477 0 : SendError( "write failed in EnvisatFile_WriteDatasetRecord()" );
1478 0 : return FAILURE;
1479 : }
1480 :
1481 0 : return SUCCESS;
1482 : }
1483 :
1484 : /*-----------------------------------------------------------------------------
1485 :
1486 : Name:
1487 : EnvisatFile_ReadDatasetRecord()
1488 :
1489 : Purpose:
1490 : Read an arbitrary dataset record.
1491 :
1492 : Description:
1493 : Note that no range checking is made on offset and size, and data may be
1494 : read from outside the dataset if they are inappropriate.
1495 :
1496 : Inputs:
1497 : self -- the file to be searched.
1498 : ds_index -- the index of dataset to access.
1499 : record_index -- the record to write.
1500 : record_buffer -- buffer to load data into
1501 :
1502 : Outputs:
1503 :
1504 : Returns:
1505 : SUCCESS or FAILURE
1506 :
1507 : -----------------------------------------------------------------------------*/
1508 :
1509 : int EnvisatFile_ReadDatasetRecord( EnvisatFile *self,
1510 : int ds_index,
1511 : int record_index,
1512 : void *buffer )
1513 :
1514 0 : {
1515 : int absolute_offset;
1516 : int result;
1517 :
1518 0 : if( ds_index < 0 || ds_index >= self->ds_count )
1519 : {
1520 0 : SendError( "Attempt to write non-existant dataset in "
1521 : "EnvisatFile_WriteDatasetRecord()" );
1522 0 : return FAILURE;
1523 : }
1524 :
1525 0 : if( record_index < 0
1526 : || record_index >= self->ds_info[ds_index]->num_dsr )
1527 : {
1528 0 : SendError( "Attempt to write beyond end of dataset in "
1529 : "EnvisatFile_WriteDatasetRecord()" );
1530 0 : return FAILURE;
1531 : }
1532 :
1533 0 : absolute_offset = self->ds_info[ds_index]->ds_offset
1534 : + record_index * self->ds_info[ds_index]->dsr_size;
1535 :
1536 0 : if( fseek( self->fp, absolute_offset, SEEK_SET ) != 0 )
1537 : {
1538 0 : SendError( "seek failed in EnvisatFile_WriteDatasetRecord()" );
1539 0 : return FAILURE;
1540 : }
1541 :
1542 0 : result = fread( buffer, 1, self->ds_info[ds_index]->dsr_size, self->fp );
1543 0 : if( result != self->ds_info[ds_index]->dsr_size )
1544 : {
1545 0 : SendError( "read failed in EnvisatFile_ReadDatasetRecord()" );
1546 0 : return FAILURE;
1547 : }
1548 :
1549 0 : return SUCCESS;
1550 : }
1551 :
1552 : /*-----------------------------------------------------------------------------
1553 :
1554 : Name:
1555 : S_NameValueList_FindKey()
1556 :
1557 : Purpose:
1558 : Search for given key in list of name/value pairs.
1559 :
1560 : Description:
1561 : Scans list looking for index of EnvisatNameValue where the key matches
1562 : (case sensitive) the passed in name.
1563 :
1564 : Inputs:
1565 : key -- the key, such as "SLICE_POSITION" being searched for.
1566 : entry_count -- the number of items in the entries array.
1567 : entries -- array of name/value structures to search.
1568 :
1569 : Outputs:
1570 :
1571 : Returns:
1572 : array index into entries, or -1 on failure.
1573 :
1574 : -----------------------------------------------------------------------------*/
1575 :
1576 : int S_NameValueList_FindKey( const char *key,
1577 : int entry_count,
1578 : EnvisatNameValue **entries )
1579 :
1580 0 : {
1581 : int i;
1582 :
1583 0 : for( i = 0; i < entry_count; i++ )
1584 : {
1585 0 : if( strcmp(entries[i]->key,key) == 0 )
1586 0 : return i;
1587 : }
1588 :
1589 0 : return -1;
1590 : }
1591 :
1592 : /*-----------------------------------------------------------------------------
1593 :
1594 : Name:
1595 : S_NameValueList_FindValue()
1596 :
1597 : Purpose:
1598 : Search for given key in list of name/value pairs, and return value.
1599 :
1600 : Description:
1601 : Returns value string or default if key not found.
1602 :
1603 : Inputs:
1604 : key -- the key, such as "SLICE_POSITION" being searched for.
1605 : entry_count -- the number of items in the entries array.
1606 : entries -- array of name/value structures to search.
1607 : default_value -- value to use if key not found.
1608 :
1609 : Outputs:
1610 :
1611 : Returns:
1612 : value string, or default if key not found.
1613 :
1614 : -----------------------------------------------------------------------------*/
1615 :
1616 : const char *S_NameValueList_FindValue( const char *key,
1617 : int entry_count,
1618 : EnvisatNameValue **entries,
1619 : const char *default_value )
1620 :
1621 0 : {
1622 : int i;
1623 :
1624 0 : i = S_NameValueList_FindKey( key, entry_count, entries );
1625 0 : if( i == -1 )
1626 0 : return default_value;
1627 : else
1628 0 : return entries[i]->value;
1629 : }
1630 :
1631 : /*-----------------------------------------------------------------------------
1632 :
1633 : Name:
1634 : S_NameValueList_Parse()
1635 :
1636 : Purpose:
1637 : Parse a block of envisat style name/value pairs into an
1638 : EnvisatNameValue structure list.
1639 :
1640 : Description:
1641 : The passed in text block should be zero terminated. The entry_count,
1642 : and entries should be pre-initialized (normally to 0 and NULL).
1643 :
1644 : Inputs:
1645 : text -- the block of text, multiple lines, to be processed.
1646 :
1647 : Outputs:
1648 : entry_count -- returns with the updated number of entries in the
1649 : entries array.
1650 : entries -- returns with updated array info structures.
1651 :
1652 : Returns:
1653 : SUCCESS or FAILURE
1654 :
1655 : -----------------------------------------------------------------------------*/
1656 :
1657 : int S_NameValueList_Parse( const char *text, int text_offset,
1658 : int *entry_count,
1659 : EnvisatNameValue ***entries )
1660 :
1661 0 : {
1662 0 : const char *next_text = text;
1663 :
1664 : /*
1665 : * Loop over each input line in the text block.
1666 : */
1667 0 : while( *next_text != '\0' )
1668 : {
1669 : char line[1024];
1670 0 : int line_len = 0, equal_index, src_char, line_offset;
1671 : EnvisatNameValue *entry;
1672 :
1673 : /*
1674 : * Extract one line of text into the "line" buffer, and remove the
1675 : * newline character. Eat leading spaces.
1676 : */
1677 0 : while( *next_text == ' ' )
1678 : {
1679 0 : next_text++;
1680 : }
1681 0 : line_offset = (int) (next_text - text) + text_offset;
1682 0 : while( *next_text != '\0' && *next_text != '\n' )
1683 : {
1684 0 : if( line_len > sizeof(line)-1 )
1685 : {
1686 0 : SendError( "S_NameValueList_Parse(): "
1687 : "Corrupt line, longer than 1024 characters." );
1688 0 : return FAILURE;
1689 : }
1690 :
1691 0 : line[line_len++] = *(next_text++);
1692 : }
1693 :
1694 0 : line[line_len] = '\0';
1695 0 : if( *next_text == '\n' )
1696 0 : next_text++;
1697 :
1698 : /*
1699 : * Blank lines are permitted. We will skip processing of any line
1700 : * that doesn't have an equal sign, under the assumption it is
1701 : * white space.
1702 : */
1703 0 : if( strstr( line, "=") == NULL )
1704 0 : continue;
1705 :
1706 : /*
1707 : * Create the name/value info structure.
1708 : */
1709 0 : entry = (EnvisatNameValue *) calloc(sizeof(EnvisatNameValue),1);
1710 0 : entry->literal_line = strdup(line);
1711 :
1712 : /*
1713 : * Capture the key. We take everything up to the equal sign. There
1714 : * shouldn't be any white space, but if so, we take it as part of the
1715 : * key.
1716 : */
1717 0 : equal_index = strstr(line, "=") - line;
1718 0 : entry->key = (char *) malloc(equal_index+1);
1719 0 : strncpy( entry->key, line, equal_index );
1720 0 : entry->key[equal_index] = '\0';
1721 0 : entry->value_offset = line_offset + equal_index + 1;
1722 :
1723 : /*
1724 : * If the next character after the equal sign is a double quote, then
1725 : * the value is a string. Suck out the text between the double quotes.
1726 : */
1727 0 : if( line[equal_index+1] == '"' )
1728 : {
1729 0 : for( src_char = equal_index + 2;
1730 0 : line[src_char] != '\0' && line[src_char] != '"';
1731 0 : src_char++ ) {}
1732 :
1733 0 : line[src_char] = '\0';
1734 0 : entry->value = strdup( line + equal_index + 2 );
1735 0 : entry->value_offset += 1;
1736 : }
1737 :
1738 : /*
1739 : * The value is numeric, and may include a units field.
1740 : */
1741 : else
1742 : {
1743 0 : for( src_char = equal_index + 1;
1744 0 : line[src_char] != '\0' && line[src_char] != '<'
1745 : && line[src_char] != ' ';
1746 0 : src_char++ ) {}
1747 :
1748 : /* capture units */
1749 0 : if( line[src_char] == '<' )
1750 : {
1751 : int dst_char;
1752 :
1753 0 : for( dst_char = src_char+1;
1754 0 : line[dst_char] != '>' && line[dst_char] != '\0';
1755 0 : dst_char++ ) {}
1756 :
1757 0 : line[dst_char] = '\0';
1758 0 : entry->units = strdup( line + src_char + 1 );
1759 : }
1760 :
1761 0 : line[src_char] = '\0';
1762 0 : entry->value = strdup( line + equal_index + 1 );
1763 : }
1764 :
1765 : /*
1766 : * Add the entry to the name/value list.
1767 : */
1768 0 : if( entries == NULL )
1769 : {
1770 0 : *entry_count = 1;
1771 0 : *entries = (EnvisatNameValue **)
1772 : calloc( 1, sizeof(EnvisatNameValue) );
1773 : }
1774 : else
1775 : {
1776 0 : (*entry_count)++;
1777 0 : *entries = (EnvisatNameValue **)
1778 : realloc( *entries, *entry_count * sizeof(EnvisatNameValue*) );
1779 : }
1780 :
1781 0 : if( *entries == NULL )
1782 : {
1783 0 : *entry_count = 0;
1784 0 : return FAILURE;
1785 : }
1786 :
1787 0 : (*entries)[*entry_count-1] = entry;
1788 : }
1789 :
1790 0 : return SUCCESS;
1791 : }
1792 :
1793 : /*-----------------------------------------------------------------------------
1794 :
1795 : Name:
1796 : S_NameValueList_Rewrite()
1797 :
1798 : Purpose:
1799 : Rewrite the values of a name/value list in the file.
1800 :
1801 : Description:
1802 :
1803 : Inputs:
1804 : fp -- the FILE to operate on.
1805 : entry_count -- number of entries to write.
1806 : entries -- array of entry descriptions.
1807 :
1808 : Returns:
1809 : SUCCESS or FAILURE
1810 :
1811 :
1812 : -----------------------------------------------------------------------------*/
1813 :
1814 : int S_NameValueList_Rewrite( FILE * fp, int entry_count,
1815 : EnvisatNameValue **entries )
1816 :
1817 0 : {
1818 : int i;
1819 :
1820 0 : for( i = 0; i < entry_count; i++ )
1821 : {
1822 0 : EnvisatNameValue *entry = entries[i];
1823 :
1824 0 : if( fseek( fp, entry->value_offset, SEEK_SET ) != 0 )
1825 : {
1826 0 : SendError( "fseek() failed writing name/value list." );
1827 0 : return FAILURE;
1828 : }
1829 :
1830 0 : if( fwrite( entry->value, 1, strlen(entry->value), fp ) !=
1831 : strlen(entry->value) )
1832 : {
1833 0 : SendError( "fwrite() failed writing name/value list." );
1834 0 : return FAILURE;
1835 : }
1836 : }
1837 :
1838 0 : return SUCCESS;
1839 : }
1840 :
1841 :
1842 : /*-----------------------------------------------------------------------------
1843 :
1844 : Name:
1845 : S_NameValueList_Destroy()
1846 :
1847 : Purpose:
1848 : Free resources associated with a name/value list.
1849 :
1850 : Description:
1851 : The count, and name/value list pointers are set to 0/NULL on completion.
1852 :
1853 : Inputs:
1854 : entry_count -- returns with the updated number of entries in the
1855 : entries array.
1856 : entries -- returns with updated array info structures.
1857 :
1858 : Outputs:
1859 : entry_count -- Set to zero.
1860 : entries -- Sett o NULL.
1861 :
1862 : Returns:
1863 :
1864 :
1865 : -----------------------------------------------------------------------------*/
1866 :
1867 : void S_NameValueList_Destroy( int *entry_count,
1868 : EnvisatNameValue ***entries )
1869 :
1870 0 : {
1871 : int i;
1872 :
1873 0 : for( i = 0; i < *entry_count; i++ )
1874 : {
1875 0 : free( (*entries)[i]->key );
1876 0 : free( (*entries)[i]->value );
1877 0 : free( (*entries)[i]->units );
1878 0 : free( (*entries)[i]->literal_line );
1879 0 : free( (*entries)[i] );
1880 : }
1881 :
1882 0 : free( *entries );
1883 :
1884 0 : *entry_count = 0;
1885 0 : *entries = NULL;
1886 0 : }
1887 :
1888 : /* EOF */
1889 :
|