
/*
 *
 * Description
 *	Write an indexed data file.
 *
 * Output
 *
 * Input
 *	pProp		Pointer to property structure from which to get data
 *	fname		Full path/file name of file to be written
 *	type		File type (OFF_ASCII or OFF_BINARY)
 *
 * Diagnostics
 *	Returns 0 if successful, -1 if unsuccessful for any reason.
 *
 * Author
 *	Randi J. Rost
 *	Digital Equipment Corp.
 *	Workstation Systems Engineering
 *	Palo Alto, CA
 *
 * History
 *	11-Nov-89	Created
 *
 */


#include <stdio.h>
#include <sys/file.h>
#include "off.h"

#define MAX_DATA_ITEMS	30

OFFWriteIndexed(pProp, fname, type)
    OFFProperty	*pProp;
    char	*fname;
    int		type;

    {
    FILE	*ascfd;
    int		binfd;
    long	nitems, nindices;
    char	*ptr;
    int		i, j, k;
    long	*lptr;
    char	format[MAX_DATA_ITEMS][10];
    int		padding[MAX_DATA_ITEMS];
    int		size[MAX_DATA_ITEMS];
    int		datasize = 0;
    int		nostrings = 1;
    long	strlength;
    long	code;
    long	zeros = 0;
    int		endpad;
    char	dstring[80];
    long	wsize;


/*  Open the file, punt if file open fails  */
    if (type == OFF_ASCII)
	{
	ascfd = fopen(fname, "w");
	if (ascfd == NULL)
	    {
	    fprintf(stderr, "OFFWriteIndexed: cannot open data file %s\n",
		    fname);
	    return(-1);
	    }
	}
    else
	{
	binfd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0666);
	if (binfd < 0)
	    {
	    fprintf(stderr, "OFFWriteIndexed: cannot open data file %s\n",
		    fname);
	    return(-1);
	    }
	code = OFF_INDEXED_MAGIC;
	write(binfd, &code, sizeof(long));
	}


/*  Write out the number of data items for the list  */
    ptr = pProp->PropData;
    lptr = (long *) ptr;
    nitems = *lptr++;
    nindices = *lptr++;
    ptr = (char *) lptr;
    if (type == OFF_ASCII)
	fprintf(ascfd,"%d\t%d\n", nitems, nindices);
    else
	{
	write(binfd, &nitems, sizeof(long));
	write(binfd, &nindices, sizeof(long));
	}

/*  Compute data size  */
    for (i = 0; i < strlen(pProp->DataFormat); i++)
	{
	switch (pProp->DataFormat[i])
	    {
	    case 'i': size[i] = sizeof(long);
		      padding[i] = ((datasize % 4) == 0) ?
				0 : 4 - datasize % 4;
		      strcpy(format[i], "%d\t");
		      break;
	    case 'f': size[i] = sizeof(float);
		      padding[i] = ((datasize % 4) == 0) ?
				0 : 4 - datasize % 4;
		      strcpy(format[i], "%g\t");
		      break;
	    case 'd': size[i] = sizeof(double);
		      padding[i] = ((datasize % 4) == 0) ?
				0 : 4 - datasize % 4;
		      strcpy(format[i], "%*.*g\t");
		      break;
	    case 'h': size[i] = sizeof(short);
		      padding[i] = ((datasize % 2) == 0) ? 0 : 1;
		      strcpy(format[i], "%d\t");
		      break;
	    case 'b': size[i] = sizeof(char);
		      padding[i] = 0;
		      strcpy(format[i], "%d\t");
		      break;
	    case 's': size[i] = sizeof(char *);
		      padding[i] = ((datasize % 4) == 0) ?
				0 : 4 - datasize % 4;
		      strcpy(format[i], "%s\t");
		      nostrings = 0;
		      break;
	    default:  fprintf(stderr, "OFFWriteIndexed: data format not ");
		      fprintf(stderr, "valid for indexed data type\n");
		      return (-1);
	    }
	datasize += padding[i] + size[i];
	}

    endpad = ((datasize % 4) == 0) ? 0 : 4 - datasize % 4;
    datasize += endpad;


    if (type == OFF_ASCII)	/* Write info to the ascii file */
	{
	for(i = 0; i < nitems; i++)
	    {
	    for(j = 0; j < strlen(pProp->DataFormat); j++)
		{
		ptr += padding[j];
		if (pProp->DataFormat[j] == 'f')
		    fprintf(ascfd, format[j], *((float *) ptr));
		else if (pProp->DataFormat[j] == 'i')
		    fprintf(ascfd, format[j], *((long *) ptr));
		else if (pProp->DataFormat[j] == 'd')
		    { /* I wouldn't have to do this if %g format worked right*/
		    sprintf(dstring, "%-30.30g", *((double *) ptr));
		    k = 0;
		    while (dstring[k] != ' ') k++;
		    fprintf(ascfd, format[j], k, k, *((double *) ptr));
		    }
		else if (pProp->DataFormat[j] == 'h')
		    fprintf(ascfd, format[j], *((short *) ptr));
		else if (pProp->DataFormat[j] == 's')
		    fprintf(ascfd, format[j], *((char **) ptr));
		else if (pProp->DataFormat[j] == 'b')
		    fprintf(ascfd, format[j], *((unsigned char *) ptr));

		ptr += size[j];
		}

	    fprintf(ascfd, "\n");
	    ptr += endpad;
	    }
	for (i = 0; i < nindices; i++)
	    {
	    fprintf(ascfd, "%hd\n", *((short *) ptr));
	    ptr += sizeof(short);
	    }
	}

    else	/* Write info to the binary file */

	{
	wsize = datasize * nitems + endpad + sizeof(short) * nindices;
	if (nostrings)
	    write(binfd, ptr, wsize); /* Write indexed data item array */
	else
	    {
	    for(i = 0; i < nitems; i++)
		{
		for(j = 0; j < strlen(pProp->DataFormat); j++)
		    {
		    ptr += padding[j];
		    if (padding[j] != 0)  write(binfd, &zeros, padding[j]);
		    if (format[j][1] != 's')
			write(binfd, ptr, size[j]);
		    else
			{
			strlength = strlen(*((char **) ptr)) + 1;
			write(binfd, &strlength, sizeof(long));
			write(binfd, *((char **) ptr), strlength);
			strlength = ((strlength % 4) == 0) ?
				0 : 4 - strlength % 4;
			write(binfd, &zeros, strlength);
			}
		    ptr += size[j];
		    }
		if (endpad != 0)  write(binfd, &zeros, endpad);
		ptr += endpad;
		}
	    write(binfd, ptr, sizeof(short) * nindices);
	    }
	}

/*  Close the data file  */
    if (type == OFF_ASCII)
	fclose(ascfd);
    else
	close(binfd);

    return(0);
    }

