Beispiel #1
0
static void FreeAttrValue (VStringConst routine, VAttrRec *a)
{
    VTypeMethods *methods;

    switch (a->repn) {

    case VAttrListRepn:
	VDestroyAttrList (a->value);
	break;

    case VBundleRepn:
	VDestroyBundle (a->value);
	break;

    case VPointerRepn:
    case VStringRepn:
	break;

    default:
	if (! (methods = VRepnMethods (a->repn)))
	    VError ("%s: %s attribute has invalid repn %d",
		    routine, a->name, a->repn);
	(methods->destroy) (a->value);
    }
}
Beispiel #2
0
static VBoolean ReadData (FILE *f, VAttrList list, VReadFileFilterProc *filter, long *offset)
{
    VAttrListPosn posn, subposn;
    VAttrList sublist;
    VBundle b;
    VRepnKind repn;
    VBoolean read_data, data_found, length_found;
    VLong data, length;
    VTypeMethods *methods;
    VPointer value;

    for (VFirstAttr (list, & posn); VAttrExists (& posn); VNextAttr (& posn)) {
	switch (VGetAttrRepn (& posn)) {

	case VAttrListRepn:

	    /* Recurse on nested attribute list: */
	    VGetAttrValue (& posn, NULL, VAttrListRepn, & sublist);
	    if (! ReadData (f, sublist, filter, offset))
		return FALSE;
	    break;

	case VBundleRepn:
	    VGetAttrValue (& posn, NULL, VBundleRepn, & b);
	    repn = VLookupType (b->type_name);

	    /* If a filter routine was supplied, ask it whether to bother
	       with the binary data: */
	    read_data = ! filter || (*filter) (b, repn);

	    /* Extract any data and length attributes in the object's value: */
	    data_found = VLookupAttr (b->list, VDataAttr, & subposn);
	    if (data_found) {
		if (! VGetAttrValue (& subposn, NULL, VLongRepn, & data)) {
		    VWarning ("VReadFile: "
			      "%s attribute's data attribute incorrect",
			      VGetAttrName (& posn));
		    return FALSE;
		}
		VDeleteAttr (& subposn);
	    }
	    length_found = VLookupAttr (b->list, VLengthAttr, & subposn);
	    if (length_found) {
		if (! VGetAttrValue (& subposn, NULL, VLongRepn, & length)) {
		    VWarning ("VReadFile: "
			      "%s attribute's length attribute incorrect",
			      VGetAttrName (& posn));
		    return FALSE;
		}
		VDeleteAttr (& subposn);
	    }

	    /* None or both must be present: */
	    if (data_found ^ length_found) {
		VWarning ("VReadFile: %s attribute has %s but not %s",
			  VGetAttrName (& posn),
			  data_found ? "data" : "length",
			  data_found ? "length" : "data");
		return FALSE;
	    }

	    /* Read the binary data associated with the object: */
	    if (data_found) {
		if (data < *offset) {
		    VWarning ("VReadFile: "
			      "%s attribute's data attribute incorrect",
			      VGetAttrName (& posn));
		    return FALSE;
		}

		if (! read_data)
		    data += length;

		/* To seek forward to the start of the data block we first
		   try fseek. That will fail on a pipe, in which case we
		   seek by reading. */
		if (data != *offset &&
		    fseek (f, (long) data - *offset, SEEK_CUR) == -1 &&
		    errno == ESPIPE &&
		    ! MySeek (f, data - *offset)) {
		    VSystemWarning ("VReadFile: Seek within file failed");
		    return FALSE;				   
		}

		if (read_data) {
		    b->data = VMalloc (b->length = length);
		    if (fread (b->data, 1, length, f) != length) {
			VWarning ("VReadFile: Read from stream failed");
			return FALSE;
		    }
		    *offset = data + length;
		} else
		    /* bug: read error occured when bundle was not read
		       by a filter function. FK 24/03/98 */
		    *offset = data;
	    }

	    /* Recurse to read binary data for sublist attributes: */
	    if (! ReadData (f, b->list, filter, offset))
		return FALSE;

	    /* If the object's type is registered and has a decode method,
	       invoke it to decode the binary data: */
	    if (read_data && repn != VUnknownRepn &&
		(methods = VRepnMethods (repn)) && methods->decode) {
		if (! (value = (methods->decode) (VGetAttrName (& posn), b)))
		    return FALSE;

		/* Replace the old typed value with the newly decoded one: */
		VSetAttrValue (& posn, NULL, repn, value);
		VDestroyBundle (b);
	    }
	    break;

	default:
	    break;
	}
    }

    return TRUE;
}