/************************************************************************* * *N write_next_row * *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Purpose: *P * This function writes the next row of the table. * The parameter row must be initialized prior to this functional, either * by being read in from an existing table or set to valid values. * A row with any empty columns should not be written out. * The parameter table must be a valid table and initialized prior to * this function, by vpf_open_table. It is assumed that there is * enough free disk space to write to the file. It is also assumed that * the file pointer (table->fp) is already opened for writing. The * variable count, set to the values in row, must be greater than 0, * otherwise, if count is -1 the vpf_write functions will lock up * (row[].count should never have a value of 0). Note that if errorfp * is used, it must be opened prior to this function. * *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Parameters: *A * row <input> == (row_type) the row to write to the table. * table <input> == (vpf_table_type *) vpf table structure. *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * History: *H * Dave Flinn July 1991 Based on read_next_row. * Barry Michaels Oct 1991 Added row as a parameter. * JTB 10/91 guaranteed function always * returns a value: * 0: record written * -1: unknown field type *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * External Variables: *X * None *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Functions Called: *F * None *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Portability: *O * This module should be ANSI C compatible. *E *************************************************************************/ long int write_next_row(row_type row, vpf_table_type * table ) { register long int i, j; char * tptr, * output ; long int recordsize = 0; long int count; id_triplet_type * keys; unsigned long int pos_for_ndx, length; int retn_val = 0; coordinate_type dummycoord = {0.0,0.0}; STORAGE_BYTE_ORDER = table->byte_order; table->nrows++; fseek(table->fp, 0L, SEEK_END); pos_for_ndx = ftell(table->fp); /* begining of new row */ for (i = 0; i < table->nfields; i++) { /* for each column */ count = row[i].count ; /* Retrieve count from row. Should be 0 if variable length null */ /* In case this column is variable length, write out count */ if (count == 0) count = 1; if ( table->header[i].count < 0 ) { Write_Vpf_Int ( &count, table->fp, 1 ) ; recordsize += sizeof ( long int ) ; } /* Now write out the data type */ switch (table->header[i].type) { case 'T': if ( count == 0 ) /* Assume this is variable length text and don't do anything */ break ; /* This loop insures that the exact number of characters are written out to disk. */ output = (char *) vpfmalloc ( count + 1 ) ; /* include null byte */ for (j = 0, tptr = (char*)row[i].ptr; j < count; j++, tptr++) if ( *tptr ) output[j] = *tptr ; else output[j] = SPACE ; output[count] = '\0' ; Write_Vpf_Char( output ,table->fp, count) ; free ( output ) ; recordsize += sizeof ( char ) * count ; break; case 'I': Write_Vpf_Int (row[i].ptr, table->fp, count ) ; recordsize += sizeof ( long int ) * count ; break; case 'S': Write_Vpf_Short (row[i].ptr, table->fp, count ) ; recordsize += sizeof ( short int ) * count ; break; case 'F': Write_Vpf_Float (row[i].ptr, table->fp, count ) ; recordsize += sizeof ( float ) * count ; break; case 'R': Write_Vpf_Double (row[i].ptr, table->fp, count ) ; recordsize += sizeof ( double ) * count ; break; case 'D': /* date has 21 chars in memory, not on disk */ Write_Vpf_Date (row[i].ptr, table->fp, count ) ; recordsize += ( sizeof ( date_type ) - 1 ) * count ; break; case 'C': if (row[i].ptr) { Write_Vpf_Coordinate(row[i].ptr,table->fp,count); } else { for (j=0;j<count;j++) Write_Vpf_Coordinate(&dummycoord,table->fp,count); } recordsize += sizeof ( coordinate_type ) * count ; break; case 'B': Write_Vpf_DoubleCoordinate(row[i].ptr,table->fp,count); recordsize += sizeof ( double_coordinate_type ) * count ; break; case 'Z': Write_Vpf_CoordinateZ(row[i].ptr,table->fp,count); recordsize += sizeof ( tri_coordinate_type ) * count ; break; case 'Y': Write_Vpf_DoubleCoordinateZ(row[i].ptr,table->fp,count); recordsize += sizeof ( double_tri_coordinate_type ) * count ; break; case 'K': keys = (id_triplet_type *) vpfmalloc (count*sizeof(id_triplet_type)) ; memcpy ( keys, row[i].ptr, count*sizeof(id_triplet_type) ) ; for (j=0;j<count;j++) recordsize += write_key ( keys[j], table->fp); free ( keys ) ; break; case 'X': /* do nothing */ break; default: return(-1); } } if ( table->xfp ) { /* only for variable length columns */ length = recordsize ; fseek( table->xfp, 0, SEEK_END ); Write_Vpf_Int ( &pos_for_ndx, table->xfp, 1 ) ; Write_Vpf_Int ( &length, table->xfp, 1 ) ; } return retn_val; }
/************************************************************************* * *N vpf_open_table * *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Purpose: *P * This function opens a vpf table and either loads it into RAM or sets * up the structure to read off of disk. *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Parameters: *A * tablename <input> == (const char *) file name of the table. * storage <input> == (storage_type) table storage mode - * either ram or disk. * mode <input> == (const char *) file mode for opening the table - * same as fopen() mode in C. * defstr <input> == (char *) table definition string used for * creating a writable table. * vpf_open_table <output> == (vpf_table_type) VPF table structure. *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * History: *H * Barry Michaels April 1991 DOS Turbo C * Dave Flinn July 1991 UNIX compatable *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * External Variables: *X * None *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Functions Called: *F *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Portability: *O * This module should be ANSI C compatible. *E *************************************************************************/ vpf_table_type vpf_open_table( const char * tablename, storage_type storage , const char * mode, char * defstr ) { vpf_table_type table; char tablepath[255], * idxname; ossim_int32 i, j; ossim_int32 tablesize, idxsize, memsize; ossim_uint32 ulval; char * diskname = "VPF data disc"; strcpy(tablepath,tablename); rightjust(tablepath); /* Parse out name and path */ j = -1; i=(long)strlen(tablepath); while (i>0) { #ifdef __MSDOS__ if (tablepath[i] == '\\') { #else if (tablepath[i] == '/') { #endif j = i; break; } i--; } strncpy(table.name,&(tablepath[j+1]),12); rightjust(table.name); strupr(table.name); table.path = (char *)vpfmalloc(((unsigned long)strlen(tablepath)+5)*(unsigned long)sizeof(char)); strcpy(table.path, tablepath); table.path[j+1] = '\0'; /* Establish a read or write table operation */ if ( mode[0] == 'r' ) table.mode = Read ; else table.mode = Write ; /*fprintf(stderr, "vpf_open_table opening %s\n", tablepath);*/ table.fp = vpfopencheck(tablepath,mode,diskname); if (table.fp == NULL) { perror(tablepath); /* #if __MSDOS__ perror(tablepath); getch(); if (getgraphmode() >= 0) closegraph(); exit(0); #endif */ free(table.path); if (table.fp) { fclose(table.fp); table.fp = NULL; } return table; } /* If file is to be created, copy the def string ptr into header for now */ if ( table.mode == Write ) table.defstr = defstr ; #ifdef __MSDOS__ tablesize = (filelength(fileno(table.fp))); #else { /* UNIX doesn't have a filelength function, so this is the best */ struct stat statbuf ; if ( stat ( tablepath, &statbuf ) < 0 ) { fprintf (stderr, "vpf_open_table: can't stat file\n" ) ; free(table.path); fclose(table.fp); table.fp = NULL; return table; } tablesize = statbuf.st_size ; } #endif /* Populate table structure with correct data, either for read or write */ table.reclen = parse_data_def(&table); if ( table.mode == Write ) { /* write out header */ rewind ( table.fp ) ; Write_Vpf_Int ( &table.ddlen, table.fp, 1 ) ; Write_Vpf_Char ( table.defstr, table.fp, table.ddlen ) ; free ( table.defstr ) ; table.defstr = (char *) NULL ; table.nrows = 0 ; } if (table.reclen > 0) { /* Index file */ table.xstorage = (storage_type)COMPUTE; if (table.mode != Write) table.nrows = (tablesize - table.ddlen)/table.reclen; table.xfp = (FILE *) NULL ; } else { idxname = strdup( tablepath ); #ifdef __MSDOS__ idxname[strlen(tablepath)-1] = 'x'; #else if (idxname[strlen(tablepath)-1] == '.') idxname[strlen(tablepath)-2] = 'x'; else idxname[strlen(tablepath)-1] = 'x'; #endif table.xfp = fopen(idxname, mode); if ((!table.xfp) && (table.mode == Read)) { perror(idxname); fprintf(stderr, "hit RETURN to continue..."); i=getc(stdin); free(idxname); for (i = 0; i < table.nfields; i++) free(table.header[i].name); free(table.header); free(table.path); fclose(table.fp); table.fp = NULL; return table; } free(idxname); /*#ifdef __MSDOS__*/ table.xstorage = (storage_type)DISK; /* Worst case default */ /*#endif*/ /* Only read in index if file is read only */ if (table.xfp && ( table.mode == Read ) ) { Read_Vpf_Int (&(table.nrows), table.xfp, 1 ) ; Read_Vpf_Int (&ulval, table.xfp, 1 ) ; idxsize = table.nrows*sizeof(index_cell) + 10L; #ifdef __MSDOS__ if ( (idxsize < (farcoreleft()/2)) && (idxsize < __64K) ) #else if (0) #endif { table.xstorage = (storage_type)RAM; table.index = (index_type)vpfmalloc(idxsize); for (i=0;i<table.nrows;i++) { Read_Vpf_Int (&(table.index[i].pos), table.xfp, 1) ; Read_Vpf_Int (&(table.index[i].length),table.xfp,1 ) ; } fclose(table.xfp); } } else if (table.mode == Write) { /* Write out dummy header record for index file. vpf_close_table finishes the job. */ Write_Vpf_Int ( &(table.ddlen), table.xfp, 1 ) ; Write_Vpf_Int ( &(table.ddlen), table.xfp, 1 ) ; table.xstorage = (storage_type)DISK; table.index = (index_type) NULL ; } } /* end of if table .reclen */ table.storage = (storage_type)DISK; #ifdef __MSDOS__ memsize = (ossim_int32)min(farcoreleft(),__64K); #else memsize = MAXINT; #endif if ( (storage != disk) && ( table.mode == Read ) ) { if (tablesize + table.nrows * table.nfields * HEAP_OVERHEAD < memsize) { fseek(table.fp,index_pos(1,table),SEEK_SET); table.row = (row_type *)vpfmalloc((table.nrows+1)*sizeof(row_type)); for (i=0;i<table.nrows;i++) { table.row[i] = read_next_row(table); } fclose(table.fp); table.storage = (storage_type)RAM; } } table.status = OPENED; return table; } /************************************************************************* * *N vpf_close_table * *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Purpose: *P * This function frees an entire table from memory. *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Parameters: *A * table <inout> == (vpf_table_type) VPF table structure. *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * History: *H * Barry Michaels May 1991 DOS Turbo C *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * External Variables: *X * None *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Functions Called: *F * None *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Portability: *O * This module should be ANSI C compatible. *E *************************************************************************/ void vpf_close_table( vpf_table_type *table ) { register ossim_int32 i; if (table->status != OPENED) { return; } /*fprintf(stderr, "vpf_close_table closing %s%s\n", table->path, table->name);*/ /* If the table is writable, write out the final record count */ if ( table->mode == Write && table->xfp ) { rewind ( table->xfp ) ; Write_Vpf_Int ( &table->nrows, table->xfp, 1 ) ; Write_Vpf_Int ( &table->ddlen, table->xfp, 1 ) ; } for (i=0;i<table->nfields;i++) { free(table->header[i].name); /* free up null text string */ if ( table->header[i].type == 'T') free(table->header[i].nullval.Char); /* free up index file string */ if (table->header[i].tdx!=(char *)NULL) free ( table->header[i].tdx ) ; /* free up narrative table string */ if (table->header[i].narrative!=(char *)NULL) { free ( table->header[i].narrative ) ; } } free(table->header); switch (table->storage) { case RAM: for (i=0;i<table->nrows;i++) free_row(table->row[i],*table); free(table->row); break; case DISK: fclose(table->fp); break; default: printf("%s%s: unknown storage flag: %d\n",table->path,table->name, table->storage); break; } switch (table->xstorage) { case RAM: free(table->index); break; case DISK: fclose(table->xfp); break; case COMPUTE: break; default: printf("%s%s: unknown index storage flag: %d\n", table->path,table->name,table->storage); break; } table->nfields = 0; free(table->path); table->status = CLOSED; } ossim_int32 is_vpf_table( const char *fname ) { FILE *fp; ossim_int32 n, ok; fp = fopen( fname, "rb" ); if (!fp) { return FALSE; } Read_Vpf_Int ( &n, fp, 1 ) ; fseek( fp, n-1, SEEK_CUR ); if (fgetc(fp) == ';') ok = TRUE; else ok = FALSE; fclose(fp); return ok; }
/************************************************************************* * *N write_key * *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Purpose: *P * This function writes an id triplet key from the specified file. * It is assumed that there is enough free disk space to write to the * file. It is also assumed that the file pointer (fp) is already opened * for writing. *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Parameters: *A * key <input> == (id_triplet_type) id triplet key. * fp <input> == (FILE *) input file pointer. * return <output> == (long int) size of the key. *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * History: *H * Dave Flinn July 1991 Based on read_key in vpftable.c *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * External Variables: *X * None *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Functions Called: *F * None *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Portability: *O * This module should be ANSI C compatible. *E *************************************************************************/ long int write_key( id_triplet_type key, FILE *fp ) { long int size = 0 ; /* to count size of key write */ unsigned char tint ; short int tshort ; /* Assume that any count value has been written before this */ /* Only write one key in this subroutine, do not write more */ Write_Vpf_Char (&(key.type),fp,1); size += sizeof ( char ) ; switch (TYPE0(key.type)) { case 0: break; case 1: tint = (unsigned char) key.id ; Write_Vpf_Char ( &tint, fp, 1 ) ; size += sizeof ( char ) ; break; case 2: tshort = (short) key.id ; Write_Vpf_Short ( &tshort, fp, 1 ) ; size += sizeof ( short int ) ; break; case 3: Write_Vpf_Int (&(key.id), fp, 1 ) ; size += sizeof ( long int ) ; break; } switch (TYPE1(key.type)) { case 0: break; case 1: tint = (unsigned char) key.tile ; Write_Vpf_Char ( &tint, fp, 1 ) ; size += sizeof ( char ) ; break; case 2: tshort = (short) key.tile ; Write_Vpf_Short ( &tshort, fp, 1 ) ; size += sizeof ( short int ) ; break; case 3: Write_Vpf_Int (&(key.tile), fp, 1 ) ; size += sizeof ( long int ) ; break; } switch (TYPE2(key.type)) { case 0: break; case 1: tint = (unsigned char) key.exid ; Write_Vpf_Char ( &tint, fp, 1 ) ; size += sizeof ( char ) ; break; case 2: tshort = (short) key.exid ; Write_Vpf_Short ( &tshort, fp, 1 ) ; size += sizeof ( short int ) ; break; case 3: Write_Vpf_Int (&(key.exid), fp, 1 ) ; size += sizeof ( long int ) ; break; } return size ; }