esig_asc.c

来自「speech signal process tools」· C语言 代码 · 共 3,198 行 · 第 1/5 页

C
3,198
字号
    }    if (!ReadAsciiDims(&rank, &dim, file))    {	DebugMsg(1, "ReadAsciiArray: couldn't read dimensions.");	return FALSE;    }    ch = GetNonSpace(file);    if (ch != ':')    {	if (dim != NULL)	    free(dim);	DebugMsg(1, "ReadAsciiArray: no colon after dimensions.");	return FALSE;    }    length = LongProd(rank, dim);    size = InternTypeSize(type);    if (length == 0)	data = NULL;    else    {	data = malloc(length*size);	if (data == NULL	    || AsciiRead(data, type, length, file) != length)	{	    if (dim != NULL)		free(dim);		DebugMsg(1, "ReadAsciiArray: couldn't read data.");	    return FALSE;	}    }    array->type = type;    array->rank = rank;    array->dim = dim;    array->data = data;    return TRUE;}/* * Read from file an Ascii field specification, together with any * folowing specifications for subfields.  Create a new FieldSpec * structure containing the result.  Assign to the "subfields" member * of the new structure a field list comprising the subfield * specifications.  Store a pointer to the new structure in the * variable whose address is "field" (unless "field" is NULL). * It is assumed that before this function is called, the full name * of the field (including the following colon) has been read and * parsed into its components, and that the components are stored * in the string array "names"; the number of components is given * by "depth".  This function uses ReadAsciiFieldStruct to create * the new structure and fill in the members other than "subfields". * It then uses ReadAsciiName and recursive calls of * ReadAsciiFieldSpec to read names and subfield specifications. * It terminates after the reading of a name that is not the name * of a subfield, or when no more names are found.  The array * "names" is updated with the components of the last name read, * if any, and the return value of ReadAsciiFieldSpec is the number * of components.  A return value of 0 indicates that no more field * names were found.  A value of -1 is an error return. */static intReadAsciiFieldSpec(FieldSpec	**field,		   int		depth,		   char		**names,		   FILE		*file){    FieldSpec	*spec;    FieldSpec	*subfield;    int		name_len;    if (!ReadAsciiFieldStruct(&spec, StrDup(names[depth-1]), file))    {	*field = NULL;	return -1;		/* Error return. */    }    name_len = ReadAsciiName(depth, names, file);    while (name_len == depth + 1)    {	name_len = ReadAsciiFieldSpec(&subfield,				      depth + 1, names, file);	if (subfield == NULL || !AddSubfield(spec, subfield))	{	    FreeFieldList(spec->subfields);	    FreeFieldSpec(spec);	    *field = NULL;	    return -1;		/* Error return. */	}    }    if (field != NULL)	*field = spec;    return name_len;}/* * Read from file the part of an Ascii field specification that follows * the initial <full name> ":".  The last component of the name is * supplied via an argument.  If successful, allocate a new FieldSpec * structure, fill in the name, type, rank, dimensions, miscellaneous * attributes, and occurrence code.  If the field data is in the header * (e.g. GLOBAL fields) also fill in the data.  Store a pointer to the * new structure in *field.  (The subfields are not read by this * function; that is the task of ReadAsciiFieldSpec.) * Return TRUE for success, FALSE for failure. */static intReadAsciiFieldStruct(FieldSpec	**field,		     char	*name,		     FILE	*file){    short	type;    short	rank;    long	*dim;    FieldSpec	*spec = NULL;    int		i;    if (ReadAsciiType(&type, file)	&& ReadAsciiDims(&rank, &dim, file)	&& (spec = NewFieldSpec(type, rank)) != NULL	&& ReadAsciiMisc(rank, &spec->units, &spec->scale,			 &spec->offset, &spec->axis_names, file)	&& ReadAsciiOccurrence(&spec->occurrence, file))    {	spec->name = name;	for (i = 0; i < rank; i++)	    spec->dim[i] = dim[i];	if (dim != NULL)	    free(dim);	if ((type == NO_TYPE	     || spec->occurrence == REQUIRED || spec->occurrence == OPTIONAL 	     || ReadAsciiData(spec, file))	    && ReadAsciiNewline(file))	{	    *field = spec;	    return TRUE;	/* Success. */	}    }    if (spec != NULL)	FreeFieldSpec(spec);    return FALSE;		/* Error return. */}/* * Attempt to read from "file" a field name consisting of 1 or more * components separated by dots ("."); each component has the syntax of * a C identifier.  Parse the name into components.  Upon normal * completion successive elements of the string array "names" contain * the component identifiers, and the return value is the number of * components. * * This function is used by ReadAsciiFieldList and ReadAsciiFieldSpec * to read and check field names in the course of reading a field list. * * A return value of 0 indicates that no name was found, i.e. the * first character read (after skipping whitespace and bracketed * comments) was not a letter or underscore.  Normally this implies * the end of a field list, and the non-letter non-underscore character * (if not EOF) is the first character of a record.  The character is * returned to the input stream by means of "ungetc" and is the first * to be read by a subsequent attempt to read a record. * * Upon entry to ReadAsciiName, a positive value of "depth" indicates * that the first "depth" elements of "names" are the components of * a previously read field name.  In this case, ReadAsciiName checks * that the name being read is one that can legally follow the * previously read name. If not, it returns an error indication of * -1 instead of the normal nonnegative value.  The criterion for * legality is that all components of the new name, except the last, * must match the corresponding components of the previously read name, * but the last component, if any, must not match.  Examples: *  1.	"names" on entry    { "aaa", "bbb", "ccc", ...} *	"depth"             3 *	read from file      "aaa.bbb.ccc.ddd" *	OK: we've just read a spec for a field "aaa.bbb.ccc", and *	  we're about to read a spec for a subfield. *	"names" on exit     { "aaa", "bbb", "ccc", "ddd", ...} *	return              4 *  2.	"names" on entru    { "aaa", "bbb", "ccc", "ddd", ...} *	"depth"             4 *	read from file      "aaa.xxx" *	OK: we've just terminated the subfield lists for "aaa.bbb.ccc" *	  and "aaa.bbb", and we're about to get another subfield of "aaa". *	"names" on exit     { "aaa", "xxx", ...} *      return              2 *  3.	"names" on entry    { "aaa", "bbb", "ccc", ...} *	"depth"             3 *	read from file      "aaa.bbb" *	Error: we must have seen "aaa.bbb" before, as an ancestor of *	  "aaa.bbb.ccc"; we shouldn't have another spec for "aaa.bbb". *      return              -1 *  4.	"names" on entry    { "aaa", "bbb", ...} *	"depth"             2 *	read from file      "aaa.bbb.ccc.ddd" *	Error: we're missing a spec for "aaa.bbb.ccc". *      return              -1 */static intReadAsciiName(int depth, char **names, FILE *file){    int     n_id;		/* number of component identifiers */    char    *id;		/* component to match */    int     n_ch;		/* number of characters */    int     ch;			/* input character */    long    alloc_size;    ch = GetNonSpace(file);    for (n_id = 0; n_id < depth; n_id++)    {	id = names[n_id];	for (n_ch = 0; id[n_ch] != '\0' && ch == id[n_ch]; n_ch++)	    ch = getc(file);	if (id[n_ch] != '\0')	    break;	else if (isalnum(ch) || ch == '_')	    break;	else if (ch != DOT)	    return -1;	ch = getc(file);    }    if (n_id == depth)    {	if (depth >= MAX_FLD_DEPTH)	    return -1;	id = names[n_id];	n_ch = 0;	alloc_size = STR_ALLOC_SIZE;	id = (char *)	    ((id == NULL)	     ? malloc(alloc_size)	     : realloc(id, alloc_size));    }    else    {	alloc_size = n_ch + STR_ALLOC_SIZE;	id = (char *) realloc(id, alloc_size);    }    if (id == NULL)	return -1;    names[n_id] = id;    if (n_ch == 0)    {	if (isalpha(ch) || ch == '_')	{	    id[n_ch++] = ch;	    ch = getc(file);	}	else if (n_id == 0)	{	    if (ch != EOF)		ungetc(ch, file);	    return 0;	}	else return -1;    }    while (isalnum(ch) || ch == '_')    {	if (n_ch >= alloc_size)	{	    alloc_size += STR_ALLOC_SIZE;	    id = (char *) realloc(id, alloc_size);	    if (id == NULL)		return -1;	    names[n_id] = id;	}	id[n_ch++] = ch;	ch = getc(file);    }    alloc_size = n_ch + 1;    id = (char *) realloc(id, alloc_size);    if (id == NULL)	return -1;    names[n_id] = id;    id[n_ch] = '\0';    ch = SkipSpace(ch, file);    if (ch != ':')	return -1;    return n_id + 1;}/* * Read from file a string of upper-case letters and underscores. * If this is a valid elib type name (e.g. "DOUBLE_COMPLEX") * assign the corresponding numeric type code to *type and return * TRUE.  In case of error return FALSE. */static intReadAsciiType(short *type, FILE *file){    char    name[MAX_TYPE_LEN];    int     ch;    int     i;    int     code;    ch = GetNonSpace(file);    for (i = 0; i < MAX_TYPE_LEN && (isupper(ch) || ch == '_'); i++)    {	name[i] = ch;	ch = getc(file);    }    if (i == MAX_TYPE_LEN)	return FALSE;    name[i] = '\0';    if (ch != EOF)	ungetc(ch, file);    code = TypeCode(name);    if (code == 0)	return FALSE;    *type = code;    return TRUE;}/* * Read a possibly empty sequence of unsigned longs (typically * array dimensions) from file.  If it's nonempty, allocate an * array to hold the values.  Assign to *rank the number of values * read.  Assign to *dim a pointer to the allocated array, if any, * or NULL if the sequence was empty.  (But if rank or dim is NULL, * omit the corresponding assignment.)  Return TRUE for success, * FALSE for error. */static intReadAsciiDims(short *rank, long **dim, FILE *file){    long    d;    long    *dd;    int     r;    /*! Check for overflow.  fscanf doesn't, and Sun's strtol doesn't. */    if (!ReadSpace(file) || fscanf(file, "%lu", &d) != 1)    {	r = 0;	dd = NULL;    }    else    {	dd = (long *) malloc(sizeof(*dd));	if (dd == NULL)	    return FALSE;	dd[0] = d;	for (r = 1;	     ReadSpace(file) && fscanf(file, "%lu", &d) == 1;	     r++)	{	    dd = (long *) realloc(dd, (r + 1) * sizeof(*dd));	    if (dd == NULL)		return FALSE;	    dd[r] = d;	}    }    if (rank != NULL)	*rank = r;    if (dim != NULL)	*dim = dd;    return TRUE;}/* * Read Ascii representations of the miscellaneous attributes * (units, scale, offset, axis_names) from file, and output the * values found by assignment to the variables *units, *scale, *offset, * and *axis_names (if defined).  If no explicit representation * for an attribute is found, omit the corresponding assignment. * (The caller is assumed to have assigned default values to the * variables before calling ReadAsciiMisc).  If any of the arguments * units, scale, offset, and axis_names is NULL, omit the corresponding * assignment.  Return TRUE upon success and FALSE in case of error. */static intReadAsciiMisc(int rank, char **units, double *scale,	      double *offset, char ***axis_names, FILE *file){    /*     * Length of longest attribute name ("axis_names"), including     * terminal null character.     */#define MAX_ATTR	11    char    attr[MAX_ATTR];    int     ch;    int     i;    char    *un;    double  sc;    double  or;    char    **ax;    char    got_units = FALSE;    char    got_scale = FALSE;    char    got_offset = FALSE;    char    got_axis_names = FALSE;    ch = GetNonSpace(file);    if (ch != '{')    {	ungetc(ch, file);	return TRUE;    }    do {	ch = GetNonSpace(file);	for (i = 0; i < MAX_ATTR && (islower(ch) || ch == '_'); i++)	{	    attr[i] = ch;	    ch = getc(file);	}	if (i == MAX_ATTR)	    return FALSE;	attr[i] = '\0';	ch = SkipSpace(ch, file);	if (ch != ':')	    return FALSE;	if (strcmp(attr, "units") == 0)	{	    if (!got_units++		&& ReadAsciiString(&un, file))	    {		if (units != NULL)		    *units = un;	    }	    else		return FALSE;	}	else if (strcmp(attr, "scale") == 0)	{	    if (!got_scale++		&& ReadAsciiDouble(&sc, file))	    {		if (scale != NULL)		    *scale = sc;	    }	    else		return FALSE;	}	else if (strcmp(attr, "offset") == 0)	{	    if (!got_offset++		&& ReadAsciiDouble(&or, file))	    {		if (offset != NULL)		    *offset = or;	    }	    else		return FALSE;	}	else if (strcmp(attr, "axis_names") == 0)	{	    if (!got_axis_names++		&& ReadAsciiAxisNames(&ax, rank, file))	    {		if (axis_names != NULL)		    *axis_names = ax;	    }	    else		return FALSE;	}	else	    return FALSE;	ch = GetNonSpace(file);    } while (ch == ';');    if (ch != '}')	return FALSE;    return TRUE;#undef MAX_ATTR}/* * Read from file a string constant consisting of Ascii printing characters * and including surrounding double quote characters("").  Interpret escape * sequences \\, \?, \', and \"  by removing the backslash.  Allocate space * to hold the string value, including terminating null character.  Store * a pointer to the string in the variable whose address is given by * string (unless string is NULL).  Return TRUE on success, FALSE on * failure. */static intReadAsciiString(char **string, FILE *file){    int     ch;    char    *str = NULL;    long    alloc_len = 0;    long    len = 0;    ch = GetNonSpace(file);    if (ch != '"')	return FALSE;    for (ch = getc(file); isprint(ch) && ch != '"'; ch = getc(file))    {	if (ch == '\\')	{	    ch = getc(file);	    switch (ch)	    {	    case '\\':	/* fall through */	    case '?':	/* fall through */	    case '\'':	/* fall through */	    case '"':		if (!AddChar(ch, &str, &alloc_len, &len))		    return FALSE;		break;	    default:		free(str);		return FALSE;	    }	}	else if (!AddChar(ch, &str, &alloc_len, &len))		return FALSE;	}    if (ch != '"' || !AddChar('\0', &str, &alloc_len, &len))    {	free(str);	return FALSE;    }    if (string != NULL)	*string = str;    return TRUE;}/* * Read a floating-point constant (with optional leading whitespace) * from file and assign the value to the variable whose address * is given by x. */static intReadAsciiDouble(double *x, FILE *file){    return (ReadOptSpace(file) && fscanf(file, "%lf", x) == 1);}/* * Read from file a comma-separated list with at most "rank" members, * each of which is either a C identifier or empty.  (This construct * occurs in the Ascii form of a specification for the miscellaneous * field attribute "axis_names".)  Allocate a pointer array of length * rank (or NULL if rank is 0) and assign to its elements: * - a string pointer for each identifier on the list, * - a NULL for each empty member of the list * - a NULL for each array position beyond the end of the list. * Store a pointer to the array (or NULL) in the variable whose * address is given by "axis_names" (unless that argument is NULL). * Return TRUE for success, FALSE for failure. */static intReadAsciiAxisNames(char ***axis_names, int rank, FILE *file){    char    **ax;    int     ch;    char    *str;    long    len;    long    alloc_len;    int     i;    if (rank == 0)    {	ax = NULL;	ch = GetNonSpace(file);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?