📄 esig_asc.c
字号:
rtn = AsciiWrite(data, type, nrec*length, file, annotate) / length; } else { rank = field->rank; recnum = annotate->recnum; annotate->recnum += nrec; if (length == 1) { if (type == ARRAY) step = 1; else { step = (annotate->width - annotate->indent - 3*rank + 1) / ApproxWidth(type); if (step < 1) step = 1; } stride = step*InternTypeSize(type); for (j = 0; nrec > 0; j += step, nrec -= step) { if (j > 0) { fprintf(file, "\n"); data = (char *) data + stride; } annotate->indent = fprintf(file, "[%ld]", j + recnum) + 3*rank + 2; for (i = 0; i < rank; i++) fprintf(file, "[0]"); fprintf(file, " "); AsciiWrite(data, type, (nrec < step) ? nrec : step, file, annotate); } } else { stride = length*InternTypeSize(type); for (j = 0; j < nrec; j++) { if (j > 0) fprintf(file, "\n"); annotate->indent = fprintf(file, "[%ld]", j + recnum); AsciiWriteSub(j*stride + (char *) data, type, length, file, rank, field->dim, annotate); } } annotate->indent = 0; } fprintf(file, "\n"); return rtn;}/* * LOCAL FUNCTION DEFINITIONS *//* * *** FUNCTIONS FOR INPUT *//* * Read Ascii data from file into the "data" member of field. * The number of elements and the data type are obtained from field. * If field->data is NULL, allocate space before reading the data. * Return TRUE on success, FALSE on failure. */static intReadAsciiData(FieldSpec *field, FILE *file){ size_t size; long length; if (file == NULL || field == NULL) { DebugMsg(1, "ReadAsciiData: NULL arguments."); return FALSE; } if (field->type == NO_TYPE) { DebugMsg(1, "ReadAsciiData: type NO_TYPE."); return FALSE; } size = InternTypeSize(field->type); length = FieldLength(field); if (length == 0) return TRUE; if (field->data == NULL) { field->data = malloc(length * size); if (field->data == NULL) { DebugMsg(1, "ReadAsciiData: allocation failure."); return FALSE; } } return (AsciiRead(field->data, field->type, length, file) == length);}/* * Read from file the Ascii representation of an item of type ARRAY, * not including the surrounding parentheses. Store the type, rank, * dimensions, and data in the members of the array structure, * allocating the necessary space for dimensions and data. * Return TRUE for success, FALSE for failure. */static intReadAsciiArray(Array *array, FILE *file){ short type; short rank; long *dim; void *data; size_t size; long length; int ch; if (!ReadAsciiType(&type, file)) { DebugMsg(1, "ReadAsciiArray: couldn't read type."); return FALSE; } if (type == NO_TYPE) { DebugMsg(1, "ReadAsciiArray: type NO_TYPE."); return FALSE; } 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -