📄 diskread.c
字号:
/* ---------------------- DATA FILE READ ROUTINES ----------------------- *//* --------------------- designed and coded by rpc ---------------------- *//* ---------------------- Version 1.5 July 1988 ----------------------- *//* ------------------------------------------------------------------------ *//* RELEASE NOTES: Version 1.0: The original version for the SUNGRAPH signal data inputmodule. Version 1.1: Modified the argument list of some routines. Other changes? Version 1.2: Added the auto error reporting feature. This feature isenabled or disabled via disk_io_erh(flag) which is in its own source file.Also changed dfe[] & ffe[] to DFE & FFE. Version 1.3: Added relative positioning to goto_block & goto_sample.Deleted all checking for lseek errors since they can't occur. Version 1.4: Increased the amount of text in error reporting and changedit to print on stderr instead of stdout. Version 1.5: Made goto_sample, read_variable, goto_block and read_blockreturn the sample or block number to be read next, i.e. the current position.*/#include "diskio.h"#include <stdio.h>#include <strings.h>#include <sys/file.h>#include <sys/types.h> /* these two files are included for the call */#include <sys/stat.h> /* to fstat in file length routine *//* variable type definitions: * * TYPE # | C TYPE | # of BYTES | FORTRAN TYPE * -------------------------------------------------- * 1 | short | 2 | integer*2 * 2 | int | 4 | integer*4 * 3 | float | 4 | real*4 */static short bytes_in[] = { 2, 4, 4 }; /* number of bytes in the data types */#define NUM_DATA_TYPES sizeof(bytes_in)/sizeof(bytes_in[0]) /* elements in bytes_in */struct file_data { char filename[MAX_FILENAME_LENG+1];/* file connected to this channel */ int fd; /* file descriptor assigned to above */ int format[2+2*MAX_VARS_PER_BLK]; /* the format of the data file */ short open; /* channel's status: 0-closed, 1-open */ short ch_type; /* channel type */ short v; /* variable # read on type 1 channels */ int next; /* next sample to read on type 1 chan */ /* next block to read on type 2 chan */ short samp_p_blk; /* total # of samples/block */ int byte_p_blk; /* total # of bytes/block */ int bytes[MAX_VARS_PER_BLK]; /* # of bytes/block for each variable */ short samp_avail; /* # of unread samples in current block */ int gap_head; /* # of bytes in block before selected variable */ int gap_total; /* # of block bytes not in selected variable */ };static struct file_data fd[MAX_CHANNELS];#define PARAM_OK -999struct errs { char routine[20]; /* name of routine where error was */ char name[MAX_FILENAME_LENG+1]; /* filename or variable name */ int param; /* illegal argument of call in error */ };static struct errs ervar = { "", "", PARAM_OK };#define DFE ".sg_data"#define FFE ".sg_format"extern int errno;extern short auto_er; /* flag to enable/disable auto error report & halt */extern long lseek();extern char *strcpy(), *strcat(), *strncat(), *rindex();/* -------------------- OPEN VARIABLE CHANNEL ROUTINE ------------------- *//* DESCRIPTION: chan_id = open_var_channel ( filename, var_name ) This routine is called to establish a new channel to access the values ofone of the variables in a data file. "filename" is the name of the file and"var_name" is the name of the variable whose values are to be read. Thevariable's values are accessed with the read_variable routine. This functionreturns a channel id ("chan_id") which is used to identify the opened channelwhen calling other disk read routines. "filename" can have an extension, butit is not mandatory.If "filename" has an extension: a) The extension is tested for validity. (eg. Is it .sg_data or one of the other types that can be read by these routines?) Valid extensions are these: .sg_data; .spd b) If the extension is valid, open_var_channel tries to open "filename". If the extension is not valid, an error is returned.If "filename" does not have an extension: a) Each valid extension is concatenated with a copy of filename and the resulting filename is tested for existance. b) If this file exists, open_var_channel tries to open it. If none of these files exist, an error is returned.If the file to be opened has the .sg_data extension, the format informationmust reside in a corresponding .sg_format file.Returned value: If there are no errors, the returned value is a channel id which is used toidentify the open channel when using other disk read routines. A valid channelid is >= 0. If an error occurs, the returned value is < 0.The following errors are detected: - filename is too long - all channels are open - there is a format file problem - the specified variable was not found - invalid extension in filename - no data file found - the data file could not be opened*/open_var_channel ( filename, var_name )char filename[], var_name[];{ int chan_id; chan_id = open_channel(filename, 1, var_name); strcpy(ervar.routine, "open_var_channel"); strncpy(ervar.name, filename, MAX_FILENAME_LENG); if (chan_id == -15) strncpy(ervar.name, var_name, MAX_FILENAME_LENG); strcat(ervar.name, ""); if (chan_id < 0 && auto_er) error_exit(chan_id); return(chan_id);}/* --------------------- OPEN BLOCK CHANNEL ROUTINE --------------------- *//* DESCRIPTION: chan_id = open_block_channel ( filename ) This routine is called to establish a new channel to access the values ofall of the variables in a data file. The values of the data file variables areaccessed with the read_block routine. This function returns a channel id("chan_id") which is used to identify the opened channel when calling otherdisk read routines. "filename" can have an extension, but it is not mandatory.If "filename" has an extension: a) The extension is tested for validity. (eg. Is it .sg_data or one of the other types that can be read by these routines?) Valid extensions are these: .sg_data; .spd b) If the extension is valid, open_var_channel tries to open "filename". If the extension is not valid, an error is returned.If "filename" does not have an extension: a) Each valid extension is concatenated with a copy of filename and the resulting filename is tested for existance. b) If this file exists, open_var_channel tries to open it. If none of these files exist, an error is returned.If the file to be opened has the .sg_data extension, the format informationmust reside in a corresponding .sg_format file.Returned value: If there are no errors, the returned value is a channel id which is used toidentify the open channel when using other disk read routines. A valid channelid is >= 0. If an error occurs, the returned value is < 0.The following errors are detected: - filename is too long - all channels are open - there is a format file problem - invalid extension in filename - no data file found - the data file could not be opened*/open_block_channel ( filename )char filename[];{ int chan_id; chan_id = open_channel(filename, 2, ""); strcpy(ervar.routine, "open_block_channel"); strncpy(ervar.name, filename, MAX_FILENAME_LENG); strcat(ervar.name, ""); if (chan_id < 0 && auto_er) error_exit(chan_id); return(chan_id);}/* ------------------------ OPEN CHANNEL ROUTINE ------------------------ *//* DESCRIPTION: chan_id = open_channel ( file, chan_type, vname ) This routine is for use only by the disk_read module; it cannot be calledfrom anywhere else. It does the actual channel opening operations for eachchannel type. "chan_type" indicates the type of channel being requested. Twochannel types are currently defined according to the type of access desired: 1 - single variable access 2 - block access (all block variables)"vname" is the name of the variable accessed on type 1 channels.*/static open_channel ( file, chan_type, vname )char file[], vname[];int chan_type;{ int format[2 + 2*MAX_VARS_PER_BLK], var_num, i, temp_fd, chan, file_status; char filename[MAX_FILENAME_LENG + sizeof(DFE)]; static char varnames[MAX_VARS_PER_BLK][MAX_VARNAME_LENG + 1]; static char *vnames[MAX_VARS_PER_BLK] = { varnames[ 0], varnames[ 1], varnames[ 2], varnames[ 3], varnames[ 4], varnames[ 5], varnames[ 6], varnames[ 7], varnames[ 8], varnames[ 9], varnames[10], varnames[11], varnames[12], varnames[13], varnames[14], varnames[15], varnames[16], varnames[17], varnames[18], varnames[19], varnames[20], varnames[21], varnames[22], varnames[23], varnames[24], varnames[25], varnames[26], varnames[27], varnames[28], varnames[29], varnames[30], varnames[31], varnames[32], varnames[33], varnames[34], varnames[35] };/* * do the easy error checking: */ if (strlen(file) > MAX_FILENAME_LENG) return(-2);/* * look for first available channel: */ chan = -1; for (i=0; i<MAX_CHANNELS; i++) { if (fd[i].open == 0) { chan = i; break; } } if (chan == -1) return(-14);/* * read format file: */ if (read_format( file, format, vnames ) < 0) return(-12);/* * if type 1 channel, find the variable number from the variable name: */ var_num = 0; if (chan_type==1) { for (i=0; i<format[1]; i++) { if (strcmp(vname, vnames[i]) == 0) { var_num = i+1; break; } } if (var_num == 0) return(-15); }/* * check for filename extension options and open the data file: */ file_status = test_filename(file, filename, 1); if (file_status == -2) return(-10); /* invalid extension */ if (file_status == -1) return(-16); /* no data file found */ if( (temp_fd = open(filename, O_RDONLY)) == -1) /* couldn't open */ { perror("The system call error in disk read is"); return(-13); }/* * write the data file structure variables: */ fd[chan].open = 1; strcpy( fd[chan].filename, file ); for (i=0; i < 2*format[1]+2; i++) fd[chan].format[i] = format[i]; fd[chan].fd = temp_fd; fd[chan].ch_type = chan_type; fd[chan].v = var_num; fd[chan].next = 1; fd[chan].samp_p_blk = 0; fd[chan].byte_p_blk = 0; for (i=1; i<=format[1]; i++) { fd[chan].samp_p_blk += format[2*i+1]; fd[chan].byte_p_blk += bytes_in[format[2*i] -1] * format[2*i+1]; fd[chan].bytes[i-1] = bytes_in[format[2*i] -1] * format[2*i+1]; } fd[chan].gap_head = 0; fd[chan].gap_total = 0; if (chan_type == 1 && format[1] > 1) /* the general case */ { fd[chan].samp_avail = format[2*var_num + 1]; fd[chan].gap_total = fd[chan].byte_p_blk - bytes_in[format[2*var_num] -1] * format[2*var_num + 1]; for (i=1; i<var_num; i++) fd[chan].gap_head += bytes_in[format[2*i] -1] * format[2*i+1]; lseek(fd[chan].fd, (long) fd[chan].gap_head, 1);/* * for testing only, print gap_head & gap_total: * printf("\n%d gap_head\n%d gap_total\n", fd[chan].gap_head, fd[chan].gap_total ); */ }/* * for testing only, print samples/block & bytes/block: * printf("\n%d samples/block\n%d bytes/block\n\n", fd[chan].samp_p_blk, fd[chan].byte_p_blk ); */ return(chan);}/* ------------------------ READ FORMAT ROUTINE ------------------------- *//* DESCRIPTION: status = read_format ( filename, format, vnames ) This routine determines the format associated with file "filename" andreturns this information. As with the filename argument in the open channelroutines, read_format accepts filenames with or without extensions. It uses thesame process that the open channel routines use to determine for what data filethe format information is sought. Hence, for a given filename, read_formatalways gets the format which corresponds to the data file opened by an openchannel routine. (However, read_format accepts filenames that end with.sg_format. Such a filename would cause an error if given to an open channelroutine.)The format array contains the following information: format[0] - file type indicator current meaning (will be expanded later): 1 if .sg_data file allows sample & block positioning; 0 if this is NOT allowed format[1] - number of variables/block in .sg_data file format[2*n] - data type of variable n in .sg_data file 1 - short; 2 - int; 3 - float format[2*n+1] - number of entries/block of variable n in .sg_data file"vnames" is an array of pointers to the names of variables saved in the datafile. Thus, vnames[0] points to the name of the first variable, vnames[1]points to the name of the second variable, etc. The format information comes from a .sg_format file when the data file isa .sg_data file. Other data file types have fixed formats which return a setof parameters stored in this routine. Below are listed the format parametersfor each of these other data file types.Format parameters for .spd data files: format[0] = 1 format[1] = 1 format[2] = 1 format[3] = 512 vnames[0] = "speech_data"Returned value: The returned value indicates the error status of the routine. If no erroroccurs, the returned value is 0. If an error occurs, the value is < 0.The following errors are detected: - filename is too long - invalid extension in filename - no data file found, so can't determine format - the format file could not be opened - the format file is not complete - invalid value read for file type - invalid value read for variables/block - invalid value read for data type - invalid value read for values/block*/read_format ( file, format, vnames )char file[], *vnames[];int format[];{ short frmt[2 + 2*MAX_VARS_PER_BLK]; int temp_fd, i, file_status; char filename[MAX_FILENAME_LENG + sizeof(FFE)]; strcpy(ervar.routine, "read_format"); strncpy(ervar.name, file, MAX_FILENAME_LENG); strcat(ervar.name, ""); if (strlen(file) > MAX_FILENAME_LENG) /* filename too long */ { if (auto_er) error_exit(-2); return(-2); }/* * check for filename extension options: */ file_status = test_filename(file, filename, 2); if (file_status == -2) /* invalid extension */ { if (auto_er) error_exit(-10); return(-10); } if (file_status == -1) /* no data file found */ { if (auto_er) error_exit(-25); return(-25); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -