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 + -
显示快捷键?