Exemplo n.º 1
0
Arquivo: Attr.c Projeto: Rollmops/via
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);
    }
}
Exemplo n.º 2
0
VBoolean VWriteFile (FILE *f, VAttrList list)
{
    DataBlock *db;
    VBundle b;
    VTypeMethods *methods;
    VRepnKind repn;
    VPointer value, ptr;
    VBoolean result, free_it;
    VList data_list;

    /* Write the FIL_Vista data file header, attribute list, and delimeter
       while queuing on data_list any binary data blocks to be written: */
    long offset = 0;
    data_list = VListCreate ();
    FailTest (fprintf (f, "%s %d ", VFileHeader, VFileVersion));
    if (! WriteAttrList (f, list, 1, &data_list, &offset)) {
	VListDestroy (data_list, VFree);
	return FALSE;
    }
    FailTest (fputs ("\n" VFileDelimiter, f));
    fflush (f);

    /* Traverse data_list to write the binary data blocks: */
    for (db = VListFirst (data_list); db; db = VListNext (data_list)) {
	repn = VGetAttrRepn (& db->posn);
	if (repn == VBundleRepn) {

	    /* A typed value includes its binary data block explicitly: */
	    VGetAttrValue (& db->posn, NULL, VBundleRepn, & b);
	    ptr = b->data;
	    free_it = FALSE;

	} else {

	    /* For any other representation, obtain the binary data block
	       from its encode_data method: */
	    VGetAttrValue (& db->posn, NULL, repn, & value);
	    methods = VRepnMethods (repn);
	    ptr = (methods->encode_data)
		(value, db->list, db->length, & free_it);
	    if (! ptr)
		goto Fail;
	}

	/* Write the binary data and free the buffer containing it if it was
	   allocated temporarily by an encode_data method: */
	if (db->length > 0) {
	    result = fwrite (ptr, 1, db->length, f) == db->length;
	    if (free_it)
		VFree (ptr);
	    if (! result)
		goto Fail;
	}
    }
    VListDestroy (data_list, VFree);
    return TRUE;

Fail:
    VWarning ("VWriteFile: Write to stream failed");
    VListDestroy (data_list, VFree);
    return FALSE;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
Arquivo: Attr.c Projeto: Rollmops/via
VAttrList VCopyAttrList (VAttrList list)
{
    VAttrList new_list = VCreateAttrList ();
    size_t name_size, value_size;
    VAttrRec *old_a, *new_a;
    VBundle old_b, new_b;
    VTypeMethods *methods;

    /* For each node of the old list: */
    for (old_a = list->next; old_a; old_a = old_a->next) {

	/* Compute the amount of storage needed for a copy of the node: */
	name_size = strlen (old_a->name);
	value_size = (old_a->repn == VStringRepn) ?
	    strlen ((VStringConst) old_a->value) + 1 : 0;

	/* Allocate that size and fill in the node's value: */
	new_a = VMalloc (sizeof (VAttrRec) + name_size + value_size);
	strcpy (new_a->name, old_a->name);
	switch (new_a->repn = old_a->repn) {

	case VAttrListRepn:
	    new_a->value = VCopyAttrList (old_a->value);
	    break;

	case VBundleRepn:
	    old_b = old_a->value;
	    new_b = VCreateBundle (old_b->type_name,
				   VCopyAttrList (old_b->list),
				   old_b->length, NULL);
	    if (old_b->length > 0) {
		new_b->data = VMalloc (old_b->length);
		memcpy (new_b->data, old_b->data, old_b->length);
	    }
	    new_a->value = new_b;
	    break;

	case VPointerRepn:
	    new_a->value = old_a->value;
	    break;

	case VStringRepn:
	    new_a->value = (VPointer) (new_a->name + name_size + 1);
	    strcpy (new_a->value, old_a->value);
	    break;

	default:
	    if (methods = VRepnMethods (new_a->repn))
		new_a->value = (methods->copy) (old_a->value);
	    else VError ("VCopyAttrList: %s attribute has invalid repn %d",
			 old_a->name, old_a->repn);
	}

	/* Append it to the new list: */
	new_a->next = NULL;
	if (new_a->prev = new_list->prev)
	    new_a->prev->next = new_a;
	if (! new_list->next)
	    new_list->next = new_a;
	new_list->prev = new_a;
    }
    return new_list;
}