VImage VSelectDestImage (VStringConst routine, VImage dest, int nbands, int nrows, int ncolumns, VRepnKind pixel_repn) { /* If no destination image was specified, allocate one: */ if (! dest) return VCreateImage (nbands, nrows, ncolumns, pixel_repn); /* Otherwise check that the destination provided has the appropriate characteristics: */ if (VImageNBands (dest) != nbands) { VWarning ("%s: Destination image has %d bands; %d expected", routine, VImageNBands (dest), nbands); return NULL; } if (VImageNRows (dest) != nrows) { VWarning ("%s: Destination image has %d rows; %d expected", routine, VImageNRows (dest), nrows); return NULL; } if (VImageNColumns (dest) != ncolumns) { VWarning ("%s: Destination image has %d columns; %d expected", routine, VImageNColumns (dest), ncolumns); return NULL; } if (VPixelRepn (dest) != pixel_repn) { VWarning ("%s: Destination image has %s pixels; %s expected", routine, VPixelRepnName (dest), VRepnName (pixel_repn)); return NULL; } return dest; }
VBoolean VWriteObjects (FILE *file, VRepnKind repn, VAttrList attributes, int nobjects, VPointer objects[]) { VAttrList list; VAttrListPosn posn; int i; VBoolean result; /* Create an attribute list if none was supplied: */ list = attributes ? attributes : VCreateAttrList (); /* Prepend to the attribute list an attribute for each object: */ for (i = nobjects - 1; i >= 0; i--) VPrependAttr (list, VRepnName (repn), NULL, repn, objects[i]); /* Write the attribute list: */ result = VWriteFile (file, list); /* Remove the attributes just prepended: */ VFirstAttr (list, & posn); for (i = 0; i < nobjects; i++) VDeleteAttr (& posn); if (list != attributes) VDestroyAttrList (list); return result; }
VBoolean VUnpackData (VRepnKind repn, size_t nels, VPointer packed, VPackOrder packed_order, size_t *length, VPointer *unpacked, VBoolean *alloced) { VPackOrder unpacked_order; size_t unpacked_elsize = VRepnSize (repn) * CHAR_BIT; size_t packed_elsize = VRepnPrecision (repn); size_t unpacked_length = nels * VRepnSize (repn); /* If a space for the unpacked data was supplied, ensure there's enough of it: */ if (! alloced && unpacked_length > *length) { VWarning ("VUnpackData: Insufficient space for unpacked data"); return FALSE; } *length = unpacked_length; /* Determine the present machine's internal byte order: */ unpacked_order = MachineByteOrder (); /* If the desired byte order matches that of the present machine's, and the unpacked and packed data element sizes are identical, just return the packed data: */ if (unpacked_order == packed_order && unpacked_elsize == packed_elsize) { if (alloced) { *unpacked = packed; *alloced = FALSE; } else if (packed != *unpacked) memcpy (*unpacked, packed, unpacked_length); return TRUE; } /* Unpack data elements into the buffer: */ if (packed_elsize == unpacked_elsize) { /* If the packed and unpacked are the same size, do a straight copy: */ if (packed != *unpacked) memcpy (*unpacked, packed, unpacked_length); /* Swap bytes if necessary: */ if (packed_order != unpacked_order && packed_elsize > 8) SwapBytes (nels, packed_elsize / 8, (char *) *unpacked); } else if (packed_elsize == 1) { /* If the elements are VBits, this unpacks them: */ VUnpackBits (nels, packed_order, (char *) packed, (char *) *unpacked); } else /* Unpacking multi-byte integers or floats is currently not supported: */ VError ("VUnpackData: " "Unpacking %s from %d to %d bits is not supported", VRepnName (repn), packed_elsize, unpacked_elsize); return TRUE; }
int VReadObjects (FILE *file, VRepnKind repn, VAttrList *attributes, VPointer **objects) { VAttrList list; VAttrListPosn posn; int i, nobjects = 0; VPointer *vector; /* Read the file's contents: */ list = VReadFile (file, NULL); if (! list) return FALSE; /* Count the objects found: */ for (VFirstAttr (list, & posn); VAttrExists (& posn); VNextAttr (& posn)) nobjects += (VGetAttrRepn (& posn) == repn); if (nobjects == 0) { VWarning ("VReadObjects: No %s objects present in stream", VRepnName (repn)); VDestroyAttrList (list); return FALSE; } /* Allocate a vector of that many object pointers: */ vector = VMalloc (nobjects * sizeof (VPointer)); /* Extract the objects from the attribute list and place them in the vector: */ for (VFirstAttr (list, & posn), i = 0; VAttrExists (& posn); ) if (VGetAttrRepn (& posn) == repn) { VGetAttrValue (& posn, NULL, repn, vector + i); VDeleteAttr (& posn); i++; } else VNextAttr (& posn); /* Return the objects and the remaining attributes: */ *attributes = list; *objects = vector; return nobjects; }
/* Parse command without license information */ VBoolean VParseCommand_nl (int noptions, VOptionDescRec options[], int *argc, char **argv) { int arg, nvalues, i, j; char *cp; VBoolean *opts_seen, result = TRUE; VOptionDescRec *opt, *opt_t; /* Note the program's name: */ VSetProgramName (argv[0]); /* Allocate storage for a set of flags indicating which arguments have been seen: */ opts_seen = VCalloc (noptions, sizeof (VBoolean)); /* Initialize any "found" flags to false, and the number field of any VArgVector values to zero: */ for (opt = options + noptions - 1; opt >= options; opt--) { if (opt->found) *opt->found = FALSE; if (opt->number == 0 && opt->value) ((VArgVector *) opt->value)->number = 0; } /* For each argument supplied with the command: */ for (arg = 1; arg < *argc; ) { cp = argv[arg++]; /* If it doesn't start with - it can't be an option: */ if (cp[0] != '-' || cp[1] == 0) continue; /* Check for -help: */ if (strcmp (cp + 1, "help") == 0) { /* If found, return FALSE to force printing of usage info: */ *argc = 1; return FALSE; } /* Look up the argument in the list of options: */ i = strlen (cp + 1); opt = NULL; for (opt_t = options + noptions - 1; opt_t >= options; opt_t--) { if (strncmp (cp + 1, opt_t->keyword, i) != 0) continue; /* not this one */ if (i == strlen (opt_t->keyword)) { opt = opt_t; break; /* an exact match */ } if (opt) goto NextArg; /* already matched another prefix */ opt = opt_t; /* note a prefix match */ } /* If the argument isn't recognized, skip it: */ if (! opt) goto NextArg; /* not recognized */ /* Remove it from the list of command arguments: */ argv[arg - 1] = 0; /* Ensure that the option has not already been seen: */ if (opts_seen[opt - options]) { fprintf (stderr, "%s: Duplicate -%s option; ignoring all but last.\n", argv[0], opt->keyword); /* If it has been seen, delete its previous value: */ if (opt->number == 0) { VFree (((VArgVector *) opt->value)->vector); ((VArgVector *) opt->value)->number = 0; } } else opts_seen[opt - options] = TRUE; /* Swallow any value(s) that follow: */ switch (opt->repn) { case VBitRepn: case VUByteRepn: case VSByteRepn: case VShortRepn: case VLongRepn: case VFloatRepn: case VDoubleRepn: case VBooleanRepn: case VStringRepn: nvalues = ParseArgValues (& arg, *argc, argv, opt); break; default: VError ("Parsing of command options with %s values " "is not implemented", VRepnName (opt->repn)); nvalues = 0; /* to quiet lint */ } /* Ensure that the expected number of arguments was found: */ if (opt->number && nvalues != opt->number) { /* Either we encountered an argument we couldn't parse, or we used up all arguments before finding the expected number of them: */ fprintf (stderr, "%s: Option -%s ", argv[0], opt->keyword); if (arg < *argc) fprintf (stderr, "has incorrect value %s.\n", argv[arg]); else if (opt->number > 1) fprintf (stderr, "requires %d values; found only %d.\n", opt->number, nvalues); else fprintf (stderr, "requires a value.\n"); result = FALSE; break; } if (opt->number == 0) ((VArgVector *) opt->value)->number = nvalues; /* Note that a value was successfully obtained for this option: */ if (opt->found) *(opt->found) = TRUE; NextArg: ; } /* Ensure that each mandatory option was seen: */ for (i = 0; i < noptions; i++) if (options[i].found == VRequiredOpt && ! opts_seen[i]) { fprintf (stderr, "%s: Option -%s must be specified.\n", argv[0], options[i].keyword); result = FALSE; } VFree ((VPointer) opts_seen); /* Squeeze together the remaining arguments in argv: */ for (i = j = 1; i < *argc; i++) if (argv[i]) argv[j++] = argv[i]; *argc = j; return result; }
VBoolean VParseCommand (int noptions, VOptionDescRec options[], int *argc, char **argv) { int arg, nvalues, i, j; char *cp; VBoolean *opts_seen, result = TRUE; VOptionDescRec *opt, *opt_t; /* Note the program's name: */ VSetProgramName (argv[0]); /* Allocate storage for a set of flags indicating which arguments have been seen: */ opts_seen = VCalloc (noptions, sizeof (VBoolean)); /* Initialize any "found" flags to false, and the number field of any VArgVector values to zero: */ for (opt = options + noptions - 1; opt >= options; opt--) { if (opt->found) *opt->found = FALSE; if (opt->number == 0 && opt->value) ((VArgVector *) opt->value)->number = 0; } /* For each argument supplied with the command: */ for (arg = 1; arg < *argc; ) { cp = argv[arg++]; /* If it doesn't start with - it can't be an option: */ if (cp[0] != '-' || cp[1] == 0) continue; /* Check for -help: */ if (strcmp (cp + 1, "license") == 0) { char* license="This program is free software; you can redistribute it and/or\n modify it under the terms of the GNU General Public License\n as published by the Free Software Foundation; either version 2\n of the License, or (at your option) any later version.\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License\n along with this program; if not, write to the Free Software\n Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n"; fprintf(stderr,"%s\n",license); exit(0); } } /* For each argument supplied with the command: */ for (arg = 1; arg < *argc; ) { cp = argv[arg++]; /* If it doesn't start with - it can't be an option: */ if (cp[0] != '-' || cp[1] == 0) continue; /* Check for -help: */ if (strcmp (cp + 1, "help") == 0) { /* If found, return FALSE to force printing of usage info: */ *argc = 1; return FALSE; } /* Look up the argument in the list of options: */ i = strlen (cp + 1); opt = NULL; for (opt_t = options + noptions - 1; opt_t >= options; opt_t--) { if (strncmp (cp + 1, opt_t->keyword, i) != 0) continue; /* not this one */ if (i == strlen (opt_t->keyword)) { opt = opt_t; break; /* an exact match */ } if (opt) goto NextArg; /* already matched another prefix */ opt = opt_t; /* note a prefix match */ } /* If the argument isn't recognized, skip it: */ if (! opt) goto NextArg; /* not recognized */ /* Remove it from the list of command arguments: */ argv[arg - 1] = 0; /* Ensure that the option has not already been seen: */ if (opts_seen[opt - options]) { fprintf (stderr, "%s: Duplicate -%s option; ignoring all but last.\n", argv[0], opt->keyword); /* If it has been seen, delete its previous value: */ if (opt->number == 0) { VFree (((VArgVector *) opt->value)->vector); ((VArgVector *) opt->value)->number = 0; } } else opts_seen[opt - options] = TRUE; /* Swallow any value(s) that follow: */ switch (opt->repn) { case VBitRepn: case VUByteRepn: case VSByteRepn: case VShortRepn: case VLongRepn: case VFloatRepn: case VDoubleRepn: case VBooleanRepn: case VStringRepn: nvalues = ParseArgValues (& arg, *argc, argv, opt); break; default: VError ("Parsing of command options with %s values " "is not implemented", VRepnName (opt->repn)); nvalues = 0; /* to quiet lint */ } /* Ensure that the expected number of arguments was found: */ if (opt->number && nvalues != opt->number) { /* Either we encountered an argument we couldn't parse, or we used up all arguments before finding the expected number of them: */ fprintf (stderr, "%s: Option -%s ", argv[0], opt->keyword); if (arg < *argc) fprintf (stderr, "has incorrect value %s.\n", argv[arg]); else if (opt->number > 1) fprintf (stderr, "requires %d values; found only %d.\n", opt->number, nvalues); else fprintf (stderr, "requires a value.\n"); result = FALSE; break; } if (opt->number == 0) ((VArgVector *) opt->value)->number = nvalues; /* Note that a value was successfully obtained for this option: */ if (opt->found) *(opt->found) = TRUE; NextArg: ; } /* Ensure that each mandatory option was seen: */ for (i = 0; i < noptions; i++) if (options[i].found == VRequiredOpt && ! opts_seen[i]) { fprintf (stderr, "%s: Option -%s must be specified.\n", argv[0], options[i].keyword); result = FALSE; } VFree ((VPointer) opts_seen); /* Squeeze together the remaining arguments in argv: */ for (i = j = 1; i < *argc; i++) if (argv[i]) argv[j++] = argv[i]; *argc = j; return result; }
static VBoolean WriteAttr (FILE *f, VAttrListPosn *posn, int indent, VList *data_list, long *offset) { int i; char *str; VRepnKind repn; VAttrList sublist; VBundle b; DataBlock *db; VTypeMethods *methods; size_t length; VPointer value; VBoolean result; VAttrListPosn subposn; /* Indent by the specified amount: */ for (i = 0; i < indent; i++) FailTest (fputc ('\t', f)); indent++; /* Output the attribute's name: */ FailTest (fprintf (f, "%s: ", VGetAttrName (posn))); /* Ouput its value: */ switch (repn = VGetAttrRepn (posn)) { case VAttrListRepn: VGetAttrValue (posn, NULL, VAttrListRepn, (VPointer) & sublist); result = WriteAttrList (f, sublist, indent, data_list, offset); break; case VBundleRepn: VGetAttrValue (posn, NULL, VBundleRepn, (VBundle) & b); if (! WriteString (f, b->type_name)) return FALSE; FailTest (fputc (' ', f)); /* If it's a typed value with binary data... */ if (b->length > 0) { /* Include "data" and "length" attributes in its attribute list: */ VPrependAttr (b->list, VLengthAttr, NULL, VLongRepn, (VLong) b->length); VPrependAttr (b->list, VDataAttr, NULL, VLongRepn, (VLong) *offset); /* Add it to the queue of binary data blocks to be written: */ *offset += b->length; db = VNew (DataBlock); db->posn = *posn; db->list = b->list; db->length = b->length; VListAppend (*data_list, db); } /* Write the typed value's attribute list: */ result = WriteAttrList (f, b->list, indent, data_list, offset); /* Remove the "data" and "length" attributes added earlier: */ if (b->length > 0) { VFirstAttr (b->list, & subposn); VDeleteAttr (& subposn); VDeleteAttr (& subposn); } break; case VStringRepn: VGetAttrValue (posn, NULL, VStringRepn, (VPointer) & str); result = WriteString (f, str); break; default: if (! (methods = VRepnMethods (repn)) || ! methods->encode_attr || ! methods->encode_data) { VWarning ("VWriteFile: " "%s attribute has unwriteable representation: %s", VGetAttrName (posn), VRepnName (repn)); return FALSE; } /* Write the type name: */ if (! WriteString (f, VRepnName (repn))) return FALSE; FailTest (fputc (' ', f)); /* Invoke the object type's encode_attr method to obtain an attribute list: */ VGetAttrValue (posn, NULL, repn, & value); sublist = (methods->encode_attr) (value, & length); /* If binary data is indicated... */ if (length > 0) { /* Include "data" and "length" attributes in the attr list: */ VPrependAttr (sublist, VLengthAttr, NULL, VLongRepn, (VLong) length); VPrependAttr (sublist, VDataAttr, NULL, VLongRepn, (VLong) *offset); *offset += length; } /* Add the object to the queue of binary data blocks to be written: */ db = VNew (DataBlock); db->posn = *posn; db->list = sublist; db->length = length; VListAppend (*data_list, db); /* Write the typed value's attribute list: */ result = WriteAttrList (f, sublist, indent, data_list, offset); /* Remove the "data" and "length" attributes added earlier: */ if (length > 0) { VFirstAttr (sublist, & subposn); VDeleteAttr (& subposn); VDeleteAttr (& subposn); } } /* Output a trailing newline: */ if (result) FailTest (fputc ('\n', f)); return result; Fail: VWarning ("VWriteFile: Write to stream failed"); return FALSE; }
static VStringConst Encode (VDictEntry *dict, VRepnKind repn, va_list *args) { VLong i_value = 0; VDouble f_value = 0.0; VString s_value = NULL; static char buf[40]; /* Fetch the attribute value: */ switch (repn) { case VBitRepn: i_value = va_arg (*args, VBitPromoted); break; case VUByteRepn: i_value = va_arg (*args, VUBytePromoted); break; case VSByteRepn: i_value = va_arg (*args, VSBytePromoted); break; case VShortRepn: i_value = va_arg (*args, VShortPromoted); break; case VLongRepn: i_value = va_arg (*args, VLongPromoted); break; case VFloatRepn: f_value = va_arg (*args, VFloatPromoted); break; case VDoubleRepn: f_value = va_arg (*args, VDoublePromoted); break; case VBooleanRepn: i_value = va_arg (*args, VBooleanPromoted); break; case VStringRepn: s_value = va_arg (*args, VString); break; default: VError ("VEncodeAttrValue: Can't encode from %s", VRepnName (repn)); } /* If its numeric, convert it to a string: */ switch (repn) { case VBitRepn: case VUByteRepn: case VSByteRepn: case VShortRepn: case VLongRepn: case VBooleanRepn: sprintf (s_value = buf, "%ld", (long) i_value); break; case VFloatRepn: case VDoubleRepn: sprintf (s_value = buf, "%.20g", (double) f_value); break; default: break; } /* If a dictionary was supplied, try to map the encoded value to a keyword: */ if (dict) switch (repn) { case VBitRepn: case VUByteRepn: case VSByteRepn: case VShortRepn: case VLongRepn: case VBooleanRepn: dict = VLookupDictValue (dict, VLongRepn, i_value); break; case VFloatRepn: case VDoubleRepn: dict = VLookupDictValue (dict, VDoubleRepn, f_value); break; case VStringRepn: dict = VLookupDictValue (dict, VStringRepn, s_value); break; default: break; } return dict ? dict->keyword : s_value; }
VBoolean VDecodeAttrValue (VStringConst str, VDictEntry *dict, VRepnKind repn, VPointer value) { VLong i_value = 0; VDouble f_value = 0.0; char *cp = NULL, buf[20]; /* If a dict is provided, see if str maps to any dict entry keyword, substituting the associated value if found: */ if (dict) { dict = VLookupDictKeyword (dict, str); /* If there's a dictionary entry, complete it: */ if (dict && ! dict->svalue) { str = NULL; dict->icached = dict->fcached = TRUE; sprintf (buf, "%ld", (long) dict->ivalue); dict->svalue = VNewString (buf); dict->fvalue = dict->ivalue; } } /* Convert to the internal representation: */ switch (repn) { case VBitRepn: case VUByteRepn: case VSByteRepn: case VShortRepn: case VLongRepn: case VBooleanRepn: if (dict) { if (dict->icached) i_value = dict->ivalue; else { dict->ivalue = i_value = strtol (dict->svalue, & cp, 0); dict->icached = TRUE; } } else i_value = strtol (str, & cp, 0); break; case VFloatRepn: case VDoubleRepn: if (dict) { if (dict->fcached) f_value = dict->fvalue; else { dict->fvalue = f_value = strtod (dict->svalue, & cp); dict->fcached = TRUE; } } else f_value = strtod (str, & cp); break; case VStringRepn: if (dict) str = dict->svalue; break; default: VError ("VDecodeAttrValue: Can't decode to %s", VRepnName (repn)); } if (cp && *cp) return FALSE; /* Store at *value: */ switch (repn) { case VBitRepn: * (VBit *) value = i_value; break; case VUByteRepn: * (VUByte *) value = i_value; break; case VSByteRepn: * (VSByte *) value = i_value; break; case VShortRepn: * (VShort *) value = i_value; break; case VLongRepn: * (VLong *) value = i_value; break; case VFloatRepn: * (VFloat *) value = f_value; break; case VDoubleRepn: * (VDouble *) value = f_value; break; case VBooleanRepn: * (VBoolean *) value = i_value; break; case VStringRepn: * (VStringConst *) value = str; break; default: break; } return TRUE; }
VDictEntry *VLookupDictValue (VDictEntry *dict, VRepnKind repn, ...) { va_list args; VLong i_value = 0; VDouble f_value = 0.0; VString s_value = NULL; VBoolean i_valid; /* Unravel the arguments passed: */ if (! dict) return NULL; va_start (args, repn); switch (repn) { case VBitRepn: i_value = va_arg (args, VBitPromoted); break; case VUByteRepn: i_value = va_arg (args, VUBytePromoted); break; case VSByteRepn: i_value = va_arg (args, VSBytePromoted); break; case VShortRepn: i_value = va_arg (args, VShortPromoted); break; case VLongRepn: i_value = va_arg (args, VLongPromoted); break; case VFloatRepn: f_value = va_arg (args, VFloatPromoted); break; case VDoubleRepn: f_value = va_arg (args, VDoublePromoted); break; case VBooleanRepn: i_value = va_arg (args, VBooleanPromoted); break; case VStringRepn: s_value = va_arg (args, VString); break; default: VError ("VLookupDictValue: Can't lookup %s value", VRepnName (repn)); } va_end (args); /* Search the dictionary by value: */ switch (repn) { case VBitRepn: case VUByteRepn: case VSByteRepn: case VShortRepn: case VLongRepn: case VBooleanRepn: for ( ; dict->keyword; dict++) { /* Is the entry's value only stored as a string? */ if (dict->svalue && ! dict->icached) { /* Yes -- try to convert the string to an integer, and cache that value: */ if (! VDecodeAttrValue (dict->svalue, NULL, VLongRepn, & dict->ivalue)) break; dict->icached = TRUE; } /* Test against the integer value stored in the entry: */ if (i_value == dict->ivalue) return dict; } break; case VFloatRepn: case VDoubleRepn: for ( ; dict->keyword; dict++) { /* Does the entry include a cached floating point value? */ if (! dict->fcached) { /* No -- obtain it from an integer or string value: */ if (dict->svalue) { if (! VDecodeAttrValue (dict->svalue, NULL, VDoubleRepn, & dict->fvalue)) break; } else dict->fvalue = dict->ivalue; dict->fcached = TRUE; } /* Test against the cached float value now stored in the entry: */ if (f_value == dict->fvalue) return dict; } break; case VStringRepn: /* In case we're searching a dictionary with only integer values stored, try to convert the supplied string value to an integer: */ i_valid = VDecodeAttrValue (s_value, NULL, VLongRepn, & i_value); for ( ; dict->keyword; dict++) { /* If the entry includes a string value, compare with it: */ if (dict->svalue) { if (strcmp (s_value, dict->svalue) == 0) return dict; } /* Otherwise, compare with its integer value: */ else if (i_valid && i_value == dict->ivalue) return dict; } break; default: break; } return NULL; }